xref: /optee_os/core/include/mm/tee_pager.h (revision d50fee0321fe6853ac6352cf0fd548666457b407)
14265a9fdSMarouene Boubakri /* SPDX-License-Identifier: BSD-2-Clause */
24265a9fdSMarouene Boubakri /*
34265a9fdSMarouene Boubakri  * Copyright (c) 2016-2021, Linaro Limited
44265a9fdSMarouene Boubakri  * Copyright (c) 2014, STMicroelectronics International N.V.
54265a9fdSMarouene Boubakri  */
64265a9fdSMarouene Boubakri 
7*d50fee03SEtienne Carriere #ifndef __MM_TEE_PAGER_H
8*d50fee03SEtienne Carriere #define __MM_TEE_PAGER_H
94265a9fdSMarouene Boubakri 
104265a9fdSMarouene Boubakri #include <kernel/abort.h>
114265a9fdSMarouene Boubakri #include <kernel/panic.h>
124265a9fdSMarouene Boubakri #include <kernel/user_ta.h>
134265a9fdSMarouene Boubakri #include <mm/core_mmu.h>
144265a9fdSMarouene Boubakri #include <mm/tee_mm.h>
154265a9fdSMarouene Boubakri #include <string.h>
164265a9fdSMarouene Boubakri #include <trace.h>
174265a9fdSMarouene Boubakri 
184265a9fdSMarouene Boubakri /*
194265a9fdSMarouene Boubakri  * tee_pager_early_init() - Perform early initialization of pager
204265a9fdSMarouene Boubakri  *
214265a9fdSMarouene Boubakri  * Panics if some error occurs
224265a9fdSMarouene Boubakri  */
234265a9fdSMarouene Boubakri void tee_pager_early_init(void);
244265a9fdSMarouene Boubakri 
254265a9fdSMarouene Boubakri /*
264265a9fdSMarouene Boubakri  * tee_pager_get_table_info() - Fills in table info for address mapped in
274265a9fdSMarouene Boubakri  * translation table managed by the pager.
284265a9fdSMarouene Boubakri  * @va:		address to look up
294265a9fdSMarouene Boubakri  * @ti:		filled in table info
304265a9fdSMarouene Boubakri  *
314265a9fdSMarouene Boubakri  * Returns true if address is in the pager translation tables else false
324265a9fdSMarouene Boubakri  */
334265a9fdSMarouene Boubakri bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti);
344265a9fdSMarouene Boubakri 
354265a9fdSMarouene Boubakri /*
364265a9fdSMarouene Boubakri  * tee_pager_phys_to_virt() - Translate physical address to virtual address
374265a9fdSMarouene Boubakri  * looking in the pager page tables
384265a9fdSMarouene Boubakri  * @pa:	address to translate
394265a9fdSMarouene Boubakri  * @len: check for length is mapped linearly in CORE_MMU_PGDIR_SIZE range
404265a9fdSMarouene Boubakri  *
414265a9fdSMarouene Boubakri  * Returns found virtual address or NULL on error
424265a9fdSMarouene Boubakri  */
434265a9fdSMarouene Boubakri void *tee_pager_phys_to_virt(paddr_t pa, size_t len);
444265a9fdSMarouene Boubakri 
454265a9fdSMarouene Boubakri /*
464265a9fdSMarouene Boubakri  * tee_pager_set_alias_area() - Initialize pager alias area
474265a9fdSMarouene Boubakri  * @mm_alias:	The alias area where all physical pages managed by the
484265a9fdSMarouene Boubakri  *		pager are aliased
494265a9fdSMarouene Boubakri  *
504265a9fdSMarouene Boubakri  * Panics if called twice or some other error occurs.
514265a9fdSMarouene Boubakri  */
524265a9fdSMarouene Boubakri void tee_pager_set_alias_area(tee_mm_entry_t *mm_alias);
534265a9fdSMarouene Boubakri 
544265a9fdSMarouene Boubakri /*
554265a9fdSMarouene Boubakri  * tee_pager_init_iv_region() - Initialized pager region for tags IVs used by RW
564265a9fdSMarouene Boubakri  *			        paged fobjs
574265a9fdSMarouene Boubakri  * @fobj:	fobj backing the region
584265a9fdSMarouene Boubakri  *
594265a9fdSMarouene Boubakri  * Panics if called twice or some other error occurs.
604265a9fdSMarouene Boubakri  *
614265a9fdSMarouene Boubakri  * Returns virtual address of start of IV region.
624265a9fdSMarouene Boubakri  */
634265a9fdSMarouene Boubakri vaddr_t tee_pager_init_iv_region(struct fobj *fobj);
644265a9fdSMarouene Boubakri 
654265a9fdSMarouene Boubakri /*
664265a9fdSMarouene Boubakri  * tee_pager_generate_authenc_key() - Generates authenc key for r/w paging
674265a9fdSMarouene Boubakri  *
684265a9fdSMarouene Boubakri  * Needs to draw random from RNG, panics if some error occurs.
694265a9fdSMarouene Boubakri  */
704265a9fdSMarouene Boubakri #ifdef CFG_WITH_PAGER
714265a9fdSMarouene Boubakri void tee_pager_generate_authenc_key(void);
724265a9fdSMarouene Boubakri #else
tee_pager_generate_authenc_key(void)734265a9fdSMarouene Boubakri static inline void tee_pager_generate_authenc_key(void)
744265a9fdSMarouene Boubakri {
754265a9fdSMarouene Boubakri }
764265a9fdSMarouene Boubakri #endif
774265a9fdSMarouene Boubakri 
784265a9fdSMarouene Boubakri /*
794265a9fdSMarouene Boubakri  * tee_pager_add_core_region() - Adds a pageable core region
804265a9fdSMarouene Boubakri  * @base:	base of covered memory region
814265a9fdSMarouene Boubakri  * @type:	type of memory region
824265a9fdSMarouene Boubakri  * @fobj:	fobj backing the region
834265a9fdSMarouene Boubakri  *
844265a9fdSMarouene Boubakri  * Non-page aligned base or size will cause a panic.
854265a9fdSMarouene Boubakri  */
864265a9fdSMarouene Boubakri void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type,
874265a9fdSMarouene Boubakri 			       struct fobj *fobj);
884265a9fdSMarouene Boubakri 
894265a9fdSMarouene Boubakri /*
904265a9fdSMarouene Boubakri  * tee_pager_add_um_region() - Adds a pageable user TA region
914265a9fdSMarouene Boubakri  * @uctx:	user mode context of the region
924265a9fdSMarouene Boubakri  * @base:	base of covered memory region
934265a9fdSMarouene Boubakri  * @fobj:	fobj of the store backing the memory region
944265a9fdSMarouene Boubakri  *
954265a9fdSMarouene Boubakri  * The mapping is created suitable to initialize the memory content while
964265a9fdSMarouene Boubakri  * loading the TA. Once the TA is properly loaded the regions should be
974265a9fdSMarouene Boubakri  * finalized with tee_pager_set_um_region_attr() to get more strict settings.
984265a9fdSMarouene Boubakri  *
994265a9fdSMarouene Boubakri  * Return TEE_SUCCESS on success, anything else if the region can't be added
1004265a9fdSMarouene Boubakri  */
1014265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1024265a9fdSMarouene Boubakri TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base,
1034265a9fdSMarouene Boubakri 				   struct fobj *fobj, uint32_t prot);
1044265a9fdSMarouene Boubakri #else
1054265a9fdSMarouene Boubakri static inline TEE_Result
tee_pager_add_um_region(struct user_mode_ctx * uctx __unused,vaddr_t base __unused,struct fobj * fobj __unused,uint32_t prot __unused)1064265a9fdSMarouene Boubakri tee_pager_add_um_region(struct user_mode_ctx *uctx __unused,
1074265a9fdSMarouene Boubakri 			vaddr_t base __unused, struct fobj *fobj __unused,
1084265a9fdSMarouene Boubakri 			uint32_t prot __unused)
1094265a9fdSMarouene Boubakri {
1104265a9fdSMarouene Boubakri 	return TEE_ERROR_NOT_SUPPORTED;
1114265a9fdSMarouene Boubakri }
1124265a9fdSMarouene Boubakri #endif
1134265a9fdSMarouene Boubakri 
1144265a9fdSMarouene Boubakri /*
1154265a9fdSMarouene Boubakri  * tee_pager_set_um_region_attr() - Set attributes of a initialized memory
1164265a9fdSMarouene Boubakri  *				    region
1174265a9fdSMarouene Boubakri  * @uctx:	user mode context of the region
1184265a9fdSMarouene Boubakri  * @base:	base of covered memory region
1194265a9fdSMarouene Boubakri  * @size:	size of covered memory region
1204265a9fdSMarouene Boubakri  * @flags:	TEE_MATTR_U* flags describing permissions of the region
1214265a9fdSMarouene Boubakri  *
1224265a9fdSMarouene Boubakri  * Return true on success of false if the region can't be updated
1234265a9fdSMarouene Boubakri  */
1244265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1254265a9fdSMarouene Boubakri bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base,
1264265a9fdSMarouene Boubakri 				  size_t size, uint32_t flags);
1274265a9fdSMarouene Boubakri #else
1284265a9fdSMarouene Boubakri static inline bool
tee_pager_set_um_region_attr(struct user_mode_ctx * uctx __unused,vaddr_t base __unused,size_t size __unused,uint32_t flags __unused)1294265a9fdSMarouene Boubakri tee_pager_set_um_region_attr(struct user_mode_ctx *uctx __unused,
1304265a9fdSMarouene Boubakri 			     vaddr_t base __unused, size_t size __unused,
1314265a9fdSMarouene Boubakri 			     uint32_t flags __unused)
1324265a9fdSMarouene Boubakri {
1334265a9fdSMarouene Boubakri 	return false;
1344265a9fdSMarouene Boubakri }
1354265a9fdSMarouene Boubakri #endif
1364265a9fdSMarouene Boubakri 
1374265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1384265a9fdSMarouene Boubakri void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base,
1394265a9fdSMarouene Boubakri 			     size_t size);
1404265a9fdSMarouene Boubakri #else
tee_pager_rem_um_region(struct user_mode_ctx * uctx __unused,vaddr_t base __unused,size_t size __unused)1414265a9fdSMarouene Boubakri static inline void tee_pager_rem_um_region(struct user_mode_ctx *uctx __unused,
1424265a9fdSMarouene Boubakri 					   vaddr_t base __unused,
1434265a9fdSMarouene Boubakri 					   size_t size __unused)
1444265a9fdSMarouene Boubakri {
1454265a9fdSMarouene Boubakri }
1464265a9fdSMarouene Boubakri #endif
1474265a9fdSMarouene Boubakri 
1484265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1494265a9fdSMarouene Boubakri TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va);
1504265a9fdSMarouene Boubakri #else
1514265a9fdSMarouene Boubakri static inline TEE_Result
tee_pager_split_um_region(struct user_mode_ctx * uctx __unused,vaddr_t va __unused)1524265a9fdSMarouene Boubakri tee_pager_split_um_region(struct user_mode_ctx *uctx __unused,
1534265a9fdSMarouene Boubakri 			  vaddr_t va __unused)
1544265a9fdSMarouene Boubakri {
1554265a9fdSMarouene Boubakri 	return TEE_ERROR_NOT_SUPPORTED;
1564265a9fdSMarouene Boubakri }
1574265a9fdSMarouene Boubakri 
1584265a9fdSMarouene Boubakri #endif
1594265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1604265a9fdSMarouene Boubakri void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va,
1614265a9fdSMarouene Boubakri 			       size_t len);
1624265a9fdSMarouene Boubakri #else
1634265a9fdSMarouene Boubakri static inline void
tee_pager_merge_um_region(struct user_mode_ctx * uctx __unused,vaddr_t va __unused,size_t len __unused)1644265a9fdSMarouene Boubakri tee_pager_merge_um_region(struct user_mode_ctx *uctx __unused,
1654265a9fdSMarouene Boubakri 			  vaddr_t va __unused, size_t len __unused)
1664265a9fdSMarouene Boubakri {
1674265a9fdSMarouene Boubakri }
1684265a9fdSMarouene Boubakri #endif
1694265a9fdSMarouene Boubakri 
1704265a9fdSMarouene Boubakri /*
1714265a9fdSMarouene Boubakri  * tee_pager_rem_uma_regions() - Remove all user TA regions
1724265a9fdSMarouene Boubakri  * @uctx:	user mode context
1734265a9fdSMarouene Boubakri  *
1744265a9fdSMarouene Boubakri  * This function is called when a user mode context is teared down.
1754265a9fdSMarouene Boubakri  */
1764265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1774265a9fdSMarouene Boubakri void tee_pager_rem_um_regions(struct user_mode_ctx *uctx);
1784265a9fdSMarouene Boubakri #else
tee_pager_rem_um_regions(struct user_mode_ctx * uctx __unused)1794265a9fdSMarouene Boubakri static inline void tee_pager_rem_um_regions(struct user_mode_ctx *uctx __unused)
1804265a9fdSMarouene Boubakri {
1814265a9fdSMarouene Boubakri }
1824265a9fdSMarouene Boubakri #endif
1834265a9fdSMarouene Boubakri 
1844265a9fdSMarouene Boubakri /*
1854265a9fdSMarouene Boubakri  * tee_pager_assign_um_tables() - Assigns translation table to a user ta
1864265a9fdSMarouene Boubakri  * @uctx:	user mode context
1874265a9fdSMarouene Boubakri  *
1884265a9fdSMarouene Boubakri  * This function is called to assign translation tables for the pageable
1894265a9fdSMarouene Boubakri  * regions of a user TA.
1904265a9fdSMarouene Boubakri  */
1914265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
1924265a9fdSMarouene Boubakri void tee_pager_assign_um_tables(struct user_mode_ctx *uctx);
1934265a9fdSMarouene Boubakri #else
1944265a9fdSMarouene Boubakri static inline void
tee_pager_assign_um_tables(struct user_mode_ctx * uctx __unused)1954265a9fdSMarouene Boubakri tee_pager_assign_um_tables(struct user_mode_ctx *uctx __unused)
1964265a9fdSMarouene Boubakri {
1974265a9fdSMarouene Boubakri }
1984265a9fdSMarouene Boubakri #endif
1994265a9fdSMarouene Boubakri 
2004265a9fdSMarouene Boubakri /*
2014265a9fdSMarouene Boubakri  * Adds physical pages to the pager to use. The supplied virtual address range
2024265a9fdSMarouene Boubakri  * is searched for mapped physical pages and unmapped pages are ignored.
2034265a9fdSMarouene Boubakri  *
2044265a9fdSMarouene Boubakri  * vaddr is the first virtual address
2054265a9fdSMarouene Boubakri  * npages is the number of pages to add
2064265a9fdSMarouene Boubakri  */
2074265a9fdSMarouene Boubakri void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap);
2084265a9fdSMarouene Boubakri 
2094265a9fdSMarouene Boubakri /*
2104265a9fdSMarouene Boubakri  * tee_pager_alloc() - Allocate read-write virtual memory from pager.
2114265a9fdSMarouene Boubakri  * @size:	size of memory in bytes
2124265a9fdSMarouene Boubakri  *
2134265a9fdSMarouene Boubakri  * @return NULL on failure or a pointer to the virtual memory on success.
2144265a9fdSMarouene Boubakri  */
2154265a9fdSMarouene Boubakri void *tee_pager_alloc(size_t size);
2164265a9fdSMarouene Boubakri 
2174265a9fdSMarouene Boubakri #ifdef CFG_PAGED_USER_TA
2184265a9fdSMarouene Boubakri /*
2194265a9fdSMarouene Boubakri  * tee_pager_pgt_save_and_release_entries() - Save dirty pages to backing store
2204265a9fdSMarouene Boubakri  * and remove physical page from translation table
2214265a9fdSMarouene Boubakri  * @pgt: page table descriptor
2224265a9fdSMarouene Boubakri  *
2234265a9fdSMarouene Boubakri  * This function is called when a translation table needs to be recycled
2244265a9fdSMarouene Boubakri  */
2254265a9fdSMarouene Boubakri void tee_pager_pgt_save_and_release_entries(struct pgt *pgt);
22608f6547eSJens Wiklander #else
22708f6547eSJens Wiklander static inline void
tee_pager_pgt_save_and_release_entries(struct pgt * pgt __unused)22808f6547eSJens Wiklander tee_pager_pgt_save_and_release_entries(struct pgt *pgt __unused)
22908f6547eSJens Wiklander {
23008f6547eSJens Wiklander }
2314265a9fdSMarouene Boubakri #endif
2324265a9fdSMarouene Boubakri 
2334265a9fdSMarouene Boubakri /*
2344265a9fdSMarouene Boubakri  * tee_pager_release_phys() - Release physical pages used for mapping
2354265a9fdSMarouene Boubakri  * @addr:	virtual address of first page to release
2364265a9fdSMarouene Boubakri  * @size:	number of bytes to release
2374265a9fdSMarouene Boubakri  *
2384265a9fdSMarouene Boubakri  * Only pages completely covered by the supplied range are affected.  This
2394265a9fdSMarouene Boubakri  * function only supplies a hint to the pager that the physical page can be
2404265a9fdSMarouene Boubakri  * reused. The caller can't expect a released memory range to hold a
2414265a9fdSMarouene Boubakri  * specific bit pattern when used next time.
2424265a9fdSMarouene Boubakri  *
2434265a9fdSMarouene Boubakri  * Note that the virtual memory allocation is still valid after this
2444265a9fdSMarouene Boubakri  * function has returned, it's just the content that may or may not have
2454265a9fdSMarouene Boubakri  * changed.
2464265a9fdSMarouene Boubakri  */
2474265a9fdSMarouene Boubakri #ifdef CFG_WITH_PAGER
2484265a9fdSMarouene Boubakri void tee_pager_release_phys(void *addr, size_t size);
2494265a9fdSMarouene Boubakri #else
tee_pager_release_phys(void * addr __unused,size_t size __unused)2504265a9fdSMarouene Boubakri static inline void tee_pager_release_phys(void *addr __unused,
2514265a9fdSMarouene Boubakri 			size_t size __unused)
2524265a9fdSMarouene Boubakri {
2534265a9fdSMarouene Boubakri }
2544265a9fdSMarouene Boubakri #endif
2554265a9fdSMarouene Boubakri 
2564265a9fdSMarouene Boubakri /*
2574265a9fdSMarouene Boubakri  * Statistics on the pager
2584265a9fdSMarouene Boubakri  */
2594265a9fdSMarouene Boubakri struct tee_pager_stats {
2604265a9fdSMarouene Boubakri 	size_t hidden_hits;
2614265a9fdSMarouene Boubakri 	size_t ro_hits;
2624265a9fdSMarouene Boubakri 	size_t rw_hits;
2634265a9fdSMarouene Boubakri 	size_t zi_released;
2644265a9fdSMarouene Boubakri 	size_t npages;		/* number of load pages */
2654265a9fdSMarouene Boubakri 	size_t npages_all;	/* number of pages */
2664265a9fdSMarouene Boubakri };
2674265a9fdSMarouene Boubakri 
2684265a9fdSMarouene Boubakri #ifdef CFG_WITH_PAGER
2694265a9fdSMarouene Boubakri void tee_pager_get_stats(struct tee_pager_stats *stats);
2704265a9fdSMarouene Boubakri bool tee_pager_handle_fault(struct abort_info *ai);
2714265a9fdSMarouene Boubakri #else /*CFG_WITH_PAGER*/
tee_pager_handle_fault(struct abort_info * ai __unused)2724265a9fdSMarouene Boubakri static inline bool tee_pager_handle_fault(struct abort_info *ai __unused)
2734265a9fdSMarouene Boubakri {
2744265a9fdSMarouene Boubakri 	return false;
2754265a9fdSMarouene Boubakri }
2764265a9fdSMarouene Boubakri 
tee_pager_get_stats(struct tee_pager_stats * stats)2774265a9fdSMarouene Boubakri static inline void tee_pager_get_stats(struct tee_pager_stats *stats)
2784265a9fdSMarouene Boubakri {
2794265a9fdSMarouene Boubakri 	memset(stats, 0, sizeof(struct tee_pager_stats));
2804265a9fdSMarouene Boubakri }
2814265a9fdSMarouene Boubakri #endif /*CFG_WITH_PAGER*/
2824265a9fdSMarouene Boubakri 
2834265a9fdSMarouene Boubakri void tee_pager_invalidate_fobj(struct fobj *fobj);
2844265a9fdSMarouene Boubakri 
2854265a9fdSMarouene Boubakri #endif /*MM_TEE_PAGER_H*/
286