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