blob: e34fa106d7c28dcfd29bbf69dc8315ddd5261c99 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
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 */
22struct 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 */
44struct 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};
81COMPILER_ASSERT(sizeof(struct rd) <= GRANULE_SIZE);
82
83/*
84 * Sets the rd's state while holding the rd granule lock.
85 */
86static 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 */
94static 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 */
103static 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 */
111static 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 */
119static 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 */
128static inline unsigned long get_rd_rec_count_unlocked(struct rd *rd)
129{
130 return SCA_READ64_ACQUIRE(&rd->rec_count);
131}
132
133static 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 */
141static inline unsigned long realm_ipa_size(struct rd *rd)
142{
143 return (1UL << realm_ipa_bits(rd));
144}
145
146static inline unsigned long realm_par_size(struct rd *rd)
147{
148 return (realm_ipa_size(rd) / 2U);
149}
150
151static 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 */
163static 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 */
181static 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
191static inline unsigned long rec_ipa_size(struct rec *rec)
192{
193 return (1UL << rec->realm_info.ipa_bits);
194}
195
196static inline unsigned long rec_par_size(struct rec *rec)
197{
198 return (rec_ipa_size(rec) / 2U);
199}
200
201static inline bool addr_in_rec_par(struct rec *rec, unsigned long addr)
202{
203 return (addr < rec_par_size(rec));
204}
205
206static 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
212static inline bool addr_in_par(struct rd *rd, unsigned long addr)
213{
214 return (addr < realm_par_size(rd));
215}
216
217enum 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
226struct 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
234static 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
240enum s2_walk_status realm_ipa_to_pa(struct rd *rd,
241 unsigned long ipa,
242 struct s2_walk_result *res);
243
244void realm_ipa_get_ripas(struct rec *rec, unsigned long ipa,
245 enum ripas *ripas_ptr, bool *s2tte_destroyed);
246#endif /* REALM_H */