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