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