1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #ifndef REALM_H
7 #define REALM_H
8 
9 #include <assert.h>
10 #include <measurement.h>
11 #include <memory.h>
12 #include <rec.h>
13 #include <table.h>
14 
15 #define REALM_STATE_NEW		0
16 #define REALM_STATE_ACTIVE	1
17 #define REALM_STATE_SYSTEM_OFF	2
18 
19 /*
20  * Stage 2 configuration of the Realm
21  */
22 struct realm_s2_context {
23 	/* Number of IPA bits */
24 	unsigned int ipa_bits;
25 
26 	/* Starting level of the stage 2 translation */
27 	int s2_starting_level;
28 
29 	/* Number of concatenated starting level rtts */
30 	unsigned int num_root_rtts;
31 
32 	/* First level RTT, pointed to by Realm TTBR */
33 	struct granule *g_rtt;
34 
35 	/* Virtual Machine Identifier */
36 	unsigned int vmid;
37 
38 	/*
39 	 * TODO: we will need other translation regime state, e.g. TCR, MAIR(?).
40 	 */
41 };
42 
43 /* struct rd is protected by the rd granule lock */
44 struct rd {
45 	/*
46 	 * 'state' & 'rec_count' are only accessed through dedicated
47 	 * primitives where the following rules apply:
48 	 *
49 	 * (1) To write the value, the RMI handler must hold the rd granule
50 	 *     lock and use a single copy atomic store with release semantics.
51 	 *
52 	 * (2) To read the value, the RMI handler must either:
53 	 *     - Hold the rd granule lock and use a 64-bit single copy
54 	 *       atomic load, or
55 	 *     - Hold the rd reference count and use a 64-bit single copy
56 	 *       atomic load with acquire semantics.
57 	 *
58 	 * Other members of the structure are accessed with rd granule lock held.
59 	 */
60 	/* 64-bit variable accessed with READ64/WRITE64/ACQUIRE semantic */
61 	unsigned long state;
62 
63 	/* Reference count */
64 	unsigned long rec_count;
65 
66 	/* Stage 2 configuration of the Realm */
67 	struct realm_s2_context s2_ctx;
68 
69 	/* Number of auxiliary REC granules for the Realm */
70 	unsigned int num_rec_aux;
71 
72 	/* Algorithm to use for measurements */
73 	enum hash_algo algorithm;
74 
75 	/* Realm measurement */
76 	unsigned char measurement[MEASUREMENT_SLOT_NR][MAX_MEASUREMENT_SIZE];
77 
78 	/* Realm Personalization Value */
79 	unsigned char rpv[RPV_SIZE];
80 };
81 COMPILER_ASSERT(sizeof(struct rd) <= GRANULE_SIZE);
82 
83 /*
84  * Sets the rd's state while holding the rd granule lock.
85  */
set_rd_state(struct rd * rd,unsigned long state)86 static inline void set_rd_state(struct rd *rd, unsigned long state)
87 {
88 	SCA_WRITE64_RELEASE(&rd->state, state);
89 }
90 
91 /*
92  * Gets the rd's state while holding the rd granule lock.
93  */
get_rd_state_locked(struct rd * rd)94 static inline unsigned long get_rd_state_locked(struct rd *rd)
95 {
96 	return SCA_READ64(&rd->state);
97 }
98 
99 /*
100  * Gets the rd's state while holding the rd's reference count, without
101  * holding the rd granule lock.
102  */
get_rd_state_unlocked(struct rd * rd)103 static inline unsigned long get_rd_state_unlocked(struct rd *rd)
104 {
105 	return SCA_READ64_ACQUIRE(&rd->state);
106 }
107 
108 /*
109  * Sets the rd's rec_count while holding the rd granule lock.
110  */
set_rd_rec_count(struct rd * rd,unsigned long val)111 static inline void set_rd_rec_count(struct rd *rd, unsigned long val)
112 {
113 	SCA_WRITE64_RELEASE(&rd->rec_count, val);
114 }
115 
116 /*
117  * Gets the rd's rec_count while holding the rd granule lock.
118  */
get_rd_rec_count_locked(struct rd * rd)119 static inline unsigned long get_rd_rec_count_locked(struct rd *rd)
120 {
121 	return SCA_READ64(&rd->rec_count);
122 }
123 
124 /*
125  * Gets the rd's rec_count while holding the rd's reference count, without
126  * holding the rd granule lock.
127  */
get_rd_rec_count_unlocked(struct rd * rd)128 static inline unsigned long get_rd_rec_count_unlocked(struct rd *rd)
129 {
130 	return SCA_READ64_ACQUIRE(&rd->rec_count);
131 }
132 
realm_ipa_bits(struct rd * rd)133 static inline unsigned long realm_ipa_bits(struct rd *rd)
134 {
135 	return rd->s2_ctx.ipa_bits;
136 }
137 
138 /*
139  * Gets the rd's IPA size.
140  */
realm_ipa_size(struct rd * rd)141 static inline unsigned long realm_ipa_size(struct rd *rd)
142 {
143 	return (1UL << realm_ipa_bits(rd));
144 }
145 
realm_par_size(struct rd * rd)146 static inline unsigned long realm_par_size(struct rd *rd)
147 {
148 	return (realm_ipa_size(rd) / 2U);
149 }
150 
realm_rtt_starting_level(struct rd * rd)151 static inline int realm_rtt_starting_level(struct rd *rd)
152 {
153 	return rd->s2_ctx.s2_starting_level;
154 }
155 
156 /*
157  * Checks that 'address' is within container's parameters.
158  *
159  * 'container_base' is the start address of the container.
160  * 'container_end' is the first address after the container.
161  * The container must not overflow.
162  */
addr_is_contained(unsigned long container_base,unsigned long container_end,unsigned long address)163 static inline bool addr_is_contained(unsigned long container_base,
164 				     unsigned long container_end,
165 				     unsigned long address)
166 {
167 	assert(container_base <= (container_end - 1));
168 	return address >= container_base && address <= (container_end - 1);
169 }
170 
171 /*
172  * Checks that region is within container's parameters.
173  *
174  * 'container_base' is the start address of the container.
175  * 'container_end' is the first address after the container.
176  * The container must not overflow.
177  * 'region_base' is the start address of the region.
178  * 'region_end' is the first address after the region.
179  * The region must not overflow.
180  */
region_is_contained(unsigned long container_base,unsigned long container_end,unsigned long region_base,unsigned long region_end)181 static inline bool region_is_contained(unsigned long container_base,
182 				       unsigned long container_end,
183 				       unsigned long region_base,
184 				       unsigned long region_end)
185 {
186 	assert(region_base <= (region_end - 1UL));
187 	return addr_is_contained(container_base, container_end, region_base) &&
188 	       addr_is_contained(container_base, container_end, region_end - 1UL);
189 }
190 
rec_ipa_size(struct rec * rec)191 static inline unsigned long rec_ipa_size(struct rec *rec)
192 {
193 	return (1UL << rec->realm_info.ipa_bits);
194 }
195 
rec_par_size(struct rec * rec)196 static inline unsigned long rec_par_size(struct rec *rec)
197 {
198 	return (rec_ipa_size(rec) / 2U);
199 }
200 
addr_in_rec_par(struct rec * rec,unsigned long addr)201 static inline bool addr_in_rec_par(struct rec *rec, unsigned long addr)
202 {
203 	return (addr < rec_par_size(rec));
204 }
205 
region_in_rec_par(struct rec * rec,unsigned long base,unsigned long end)206 static inline bool region_in_rec_par(struct rec *rec,
207 				     unsigned long base, unsigned long end)
208 {
209 	return region_is_contained(0UL, rec_par_size(rec), base, end);
210 }
211 
addr_in_par(struct rd * rd,unsigned long addr)212 static inline bool addr_in_par(struct rd *rd, unsigned long addr)
213 {
214 	return (addr < realm_par_size(rd));
215 }
216 
217 enum s2_walk_status {
218 	/* Successful translation */
219 	WALK_SUCCESS,
220 	/* Parameter 'ipa' is unaligned or is not Protected IPA */
221 	WALK_INVALID_PARAMS,
222 	/* Mapping is not in the page table */
223 	WALK_FAIL
224 };
225 
226 struct s2_walk_result {
227 	unsigned long pa;
228 	unsigned long rtt_level;
229 	enum ripas ripas;
230 	bool destroyed;
231 	struct granule *llt;
232 };
233 
s2_walk_result_match_ripas(struct s2_walk_result * res,enum ripas ripas)234 static inline bool s2_walk_result_match_ripas(struct s2_walk_result *res,
235 					      enum ripas ripas)
236 {
237 	return (!res->destroyed && (res->ripas == ripas));
238 }
239 
240 enum s2_walk_status realm_ipa_to_pa(struct rd *rd,
241 				    unsigned long ipa,
242 				    struct s2_walk_result *res);
243 
244 enum s2_walk_status realm_ipa_get_ripas(struct rec *rec, unsigned long ipa,
245 					enum ripas *ripas_ptr,
246 					unsigned long *rtt_level);
247 #endif /* REALM_H */
248