1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2016, Linaro Limited
4 */
5 #ifndef MM_PGT_CACHE_H
6 #define MM_PGT_CACHE_H
7
8 #ifdef CFG_WITH_LPAE
9 #define PGT_SIZE (4 * 1024)
10 #define PGT_NUM_PGT_PER_PAGE 1
11 #else
12 #define PGT_SIZE (1 * 1024)
13 #define PGT_NUM_PGT_PER_PAGE 4
14 #endif
15
16 #include <assert.h>
17 #include <kernel/tee_ta_manager.h>
18 #include <sys/queue.h>
19 #include <types_ext.h>
20 #include <util.h>
21
22 struct ts_ctx;
23
24 struct pgt {
25 void *tbl;
26 vaddr_t vabase;
27 #if !defined(CFG_CORE_PREALLOC_EL0_TBLS)
28 struct ts_ctx *ctx;
29 #endif
30 bool populated;
31 #if defined(CFG_PAGED_USER_TA)
32 uint16_t num_used_entries;
33 #endif
34 #if defined(CFG_CORE_PREALLOC_EL0_TBLS) || \
35 (defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE))
36 struct pgt_parent *parent;
37 #endif
38 SLIST_ENTRY(pgt) link;
39 };
40
41 /*
42 * A proper value for PGT_CACHE_SIZE depends on many factors: CFG_WITH_LPAE,
43 * CFG_TA_ASLR, size of TA, size of memrefs passed to TA, CFG_ULIBS_SHARED and
44 * possibly others. The value is based on the number of threads as an indicator
45 * on how large the system might be.
46 */
47 #if CFG_NUM_THREADS < 2
48 #define PGT_CACHE_SIZE 4
49 #elif (CFG_NUM_THREADS == 2 && !defined(CFG_WITH_LPAE))
50 #define PGT_CACHE_SIZE 8
51 #else
52 #define PGT_CACHE_SIZE ROUNDUP(CFG_NUM_THREADS * 2, PGT_NUM_PGT_PER_PAGE)
53 #endif
54
55 SLIST_HEAD(pgt_cache, pgt);
56 struct user_mode_ctx;
57
58 bool pgt_check_avail(struct user_mode_ctx *uctx);
59
60 /*
61 * pgt_get_all() - makes all needed translation tables available
62 * @uctx: the context to own the tables
63 *
64 * Guaranteed to succeed, but may need to sleep for a while to get all the
65 * needed translation tables.
66 */
67 #if defined(CFG_CORE_PREALLOC_EL0_TBLS)
pgt_get_all(struct user_mode_ctx * uctx __unused)68 static inline void pgt_get_all(struct user_mode_ctx *uctx __unused) { }
69 #else
70 void pgt_get_all(struct user_mode_ctx *uctx);
71 #endif
72
73 /*
74 * pgt_put_all() - informs the translation table manager that these tables
75 * will not be needed for a while
76 * @uctx: the context owning the tables to make inactive
77 */
78 #if defined(CFG_CORE_PREALLOC_EL0_TBLS)
pgt_put_all(struct user_mode_ctx * uctx __unused)79 static inline void pgt_put_all(struct user_mode_ctx *uctx __unused) { }
80 #else
81 void pgt_put_all(struct user_mode_ctx *uctx);
82 #endif
83
84 void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end);
85 void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last);
86
87 #if defined(CFG_CORE_PREALLOC_EL0_TBLS)
pgt_pop_from_cache_list(vaddr_t vabase __unused,struct ts_ctx * ctx __unused)88 static inline struct pgt *pgt_pop_from_cache_list(vaddr_t vabase __unused,
89 struct ts_ctx *ctx __unused)
90 { return NULL; }
pgt_push_to_cache_list(struct pgt * pgt __unused)91 static inline void pgt_push_to_cache_list(struct pgt *pgt __unused) { }
92 #else
93 struct pgt *pgt_pop_from_cache_list(vaddr_t vabase, struct ts_ctx *ctx);
94 void pgt_push_to_cache_list(struct pgt *pgt);
95 #endif
96
97 #if defined(CFG_CORE_PREALLOC_EL0_TBLS)
pgt_init(void)98 static inline void pgt_init(void) { }
99 #else
100 void pgt_init(void);
101 #endif
102
103 void pgt_flush(struct user_mode_ctx *uctx);
104
105 #if defined(CFG_PAGED_USER_TA)
pgt_inc_used_entries(struct pgt * pgt)106 static inline void pgt_inc_used_entries(struct pgt *pgt)
107 {
108 pgt->num_used_entries++;
109 assert(pgt->num_used_entries);
110 }
111
pgt_dec_used_entries(struct pgt * pgt)112 static inline void pgt_dec_used_entries(struct pgt *pgt)
113 {
114 assert(pgt->num_used_entries);
115 pgt->num_used_entries--;
116 }
117
pgt_set_used_entries(struct pgt * pgt,size_t val)118 static inline void pgt_set_used_entries(struct pgt *pgt, size_t val)
119 {
120 pgt->num_used_entries = val;
121 }
122
123 #else
pgt_inc_used_entries(struct pgt * pgt __unused)124 static inline void pgt_inc_used_entries(struct pgt *pgt __unused)
125 {
126 }
127
pgt_dec_used_entries(struct pgt * pgt __unused)128 static inline void pgt_dec_used_entries(struct pgt *pgt __unused)
129 {
130 }
131
pgt_set_used_entries(struct pgt * pgt __unused,size_t val __unused)132 static inline void pgt_set_used_entries(struct pgt *pgt __unused,
133 size_t val __unused)
134 {
135 }
136
137 #endif
138
139 #endif /*MM_PGT_CACHE_H*/
140