1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #ifndef GRANULE_TYPES_H
7 #define GRANULE_TYPES_H
8 
9 #include <spinlock.h>
10 
11 /*
12  * Locking Order
13  * -------------
14  * Granules must be locked in a specific order to prevent deadlocks.
15  *
16  * We define two classes of granule states: `external` and `internal`.
17  *
18  * A granule state belongs to the `external` class iff _any_ parameter to _any_
19  * RMI command is an address of a granule which is expected to be in that state
20  * i.e the lock is only acquired if the granule state of the address in RMI
21  * command matches to that of the expected state.
22  *
23  * The following granule states are `external`:
24  *
25  * - GRANULE_STATE_NS
26  * - GRANULE_STATE_DELEGATED
27  * - GRANULE_STATE_RD
28  * - GRANULE_STATE_REC
29  *
30  * Otherwise a granule state is considered `internal`.
31  *
32  * The following granule states are `internal`:
33  *
34  * - GRANULE_STATE_RTT
35  * - GRANULE_STATE_DATA
36  * - GRANULE_STATE_REC_AUX
37  *
38  * The following locking rules must be followed in all cases:
39  *
40  * 1. Granules expected to be in an `external` state must be locked before
41  *    locking any granules in an `internal` state.
42  *
43  * 2. Granules expected to be in an `external` state must be locked in order
44  *    of their physical address, starting with the lowest address.
45  *
46  * 3. Once a granule expected to be in an `external` state has been locked, its
47  *    state must be checked against the expected state. If these do not match,
48  *    the granule must be unlocked and no further granules may be locked.
49  *
50  * 4. Granules in an `internal` state must be locked in order of state:
51  *    1. `RTT`
52  *    2. `DATA`
53  *    3. `REC_AUX`
54  *
55  * 5. Granules in the same `internal` state must be locked in the order defined
56  *    below for that specific state.
57  *
58  * A granule's state can be changed iff the granule is locked.
59  *
60  * Invariants
61  * ----------
62  * GRANULE_STATE_DELEGATED is special, in that it is the gateway between the
63  * non-secure and realm world.  We maintain the property that any unlocked
64  * granule with state == GRANULE_STATE_DELEGATED contains only zeroes; while
65  * locked these may contain non-zero values.
66  */
67 
68 enum granule_state {
69 	/*
70 	 * Non-Secure granule (external)
71 	 *
72 	 * Granule content is not protected by granule::lock, as it is always
73 	 * subject to reads and writes from the NS world.
74 	 */
75 	GRANULE_STATE_NS,
76 	/*
77 	 * TODO: remove the next line when spec aligment is done
78 	 * currently this has been renamed in alp03 and is needed for CBMC testbench
79 	 */
80 	GRANULE_STATE_UNDELEGATED = GRANULE_STATE_NS,
81 	/*
82 	 * Delegated Granule (external)
83 	 *
84 	 * Granule content is protected by granule::lock.
85 	 *
86 	 * No references are held on this granule type.
87 	 */
88 	GRANULE_STATE_DELEGATED,
89 	/*
90 	 * Realm Descriptor Granule (external)
91 	 *
92 	 * Granule content is protected by granule::lock.
93 	 *
94 	 * A reference is held on this granule:
95 	 * - For each associated REC granule.
96 	 *
97 	 * The RD may only be destroyed when the following objects
98 	 * have a reference count of zero:
99 	 * - The root-level RTT
100 	 */
101 	GRANULE_STATE_RD,
102 	/*
103 	 * Realm Execution Context Granule (external)
104 	 *
105 	 * Granule content (see struct rec) comprises execution
106 	 * context state and cached realm information copied from the RD.
107 	 *
108 	 * Execution context is not protected by granule::lock, because we can't
109 	 * enter a Realm while holding the lock.
110 	 *
111 	 * The following rules with respect to the granule's reference apply:
112 	 * - A reference is held on this granule when a REC is running.
113 	 * - As REC cannot be run on two PEs at the same time, the maximum
114 	 *   value of the reference count is one.
115 	 * - When the REC in entered, the reference count is incremented
116 	 *   (set to 1) atomically while granule::lock is held.
117 	 * - When the REC exits, the reference counter is released (set to 0)
118 	 *   atomically with store-release semantics without granule::lock being
119 	 *   held.
120 	 * - The RMM can access the granule's content on the entry and exit path
121 	 *   from the REC while the reference is held.
122 	 */
123 	GRANULE_STATE_REC,
124 	/*
125 	 * Realm Execution Context auxiliary granule (internal)
126 	 *
127 	 * Granule auxiliary content is used to store any state that cannot
128 	 * fit in the main REC page. This is typically used for context
129 	 * save/restore of PE features like SVE, SME, etc.
130 	 *
131 	 * Granule content is not protected by granule::lock nor the reference
132 	 * count. The RMM can access the content of the auxiliary granules
133 	 * only while holding a lock or reference to the parent REC granule.
134 	 *
135 	 * The granule::lock is held during a state change to
136 	 * GRANULE_STATE_REC_AUX and from GRANULE_STATE_REC_AUX.
137 	 *
138 	 * The complete internal locking order when changing REC_AUX
139 	 * granule's state is:
140 	 *
141 	 * REC -> REC_AUX[0] -> REC_AUX[1] -> ... -> REC_AUX[n-1]
142 	 */
143 	GRANULE_STATE_REC_AUX,
144 
145 	/*
146 	 * Data Granule (internal)
147 	 *
148 	 * Granule content is not protected by granule::lock, as it is always
149 	 * subject to reads and writes from within a Realm.
150 	 *
151 	 * A granule in this state is always referenced from exactly one entry
152 	 * in an RTT granule which must be locked before locking this granule.
153 	 * Only a single DATA granule can be locked at a time.
154 	 * The complete internal locking order for DATA granules is:
155 	 *
156 	 * RD -> RTT -> RTT -> ... -> DATA
157 	 *
158 	 * No references are held on this granule type.
159 	 */
160 	GRANULE_STATE_DATA,
161 	/*
162 	 * RTT Granule (internal)
163 	 *
164 	 * Granule content is protected by granule::lock.
165 	 *
166 	 * Granule content is protected by granule::lock, but hardware
167 	 * translation table walks may read the RTT at any point in time.
168 	 * TODO: do we wish/need to use hardware access flag management?
169 	 *
170 	 * Multiple granules in this state can only be locked at the same time
171 	 * if they are part of the same tree, and only in topological order
172 	 * from root to leaf. The topological order of concatenated root level
173 	 * RTTs is from lowest address to highest address.
174 	 *
175 	 * The complete internal locking order for RTT granules is:
176 	 *
177 	 * RD -> [RTT] -> ... -> RTT
178 	 *
179 	 * A reference is held on this granule for each entry in the RTT that
180 	 * refers to a granule:
181 	 *   - Table s2tte.
182 	 *   - Valid s2tte.
183 	 *   - Valid_NS s2tte.
184 	 *   - Assigned s2tte.
185 	 */
186 	GRANULE_STATE_RTT
187 };
188 
189 struct granule {
190 	/*
191 	 * @lock protects the struct granule itself. Take this lock whenever
192 	 * inspecting or modifying any other fields in this struct.
193 	 */
194 	spinlock_t lock;
195 
196 	/*
197 	 * @state is the state of the granule.
198 	 */
199 	enum granule_state state;
200 
201 	/*
202 	 * @refcount counts RMM and realm references to this granule with the
203 	 * following rules:
204 	 *  - The @state of the granule cannot be modified when @refcount
205 	 *    is non-zero.
206 	 *  - When a granule is mapped into the RMM, either the granule lock
207 	 *    must be held or a reference must be held.
208 	 *  - The content of the granule itself can be modified when
209 	 *    @refcount is non-zero without holding @lock.  However, specific
210 	 *    types of granules may impose further restrictions on concurrent
211 	 *    access.
212 	 */
213 	unsigned long refcount;
214 };
215 
216 #endif /* GRANULE_TYPES_H */
217