@@ -87,7 +87,7 @@ function isInvalidPTE(p : pteAttribs, ext : extPte) -> bool = {
87
87
88
88
union PTE_Check = {
89
89
PTE_Check_Success : ext_ptw ,
90
- PTE_Check_Failure : ext_ptw
90
+ PTE_Check_Failure : ( ext_ptw , ext_ptw_fail )
91
91
}
92
92
93
93
val checkPTEPermission_SC_caveat : Ext_PTE_Bits -> ext_ptw_scm
@@ -117,6 +117,51 @@ function checkPTEPermission_LC_caveat(p, e) =
117
117
else PTW_LCM_TRAP
118
118
}
119
119
120
+ val checkPTEPermission_LC_caveat_datadep : (ext_ptw_lcm , ext_ptw ) -> PTE_Check effect { rreg }
121
+ function checkPTEPermission_LC_caveat_datadep (lcav , ext_ptw ) = {
122
+ let ext_ptw ' = ext_ptw_join_lcm (ext_ptw , lcav );
123
+ match (lcav ) {
124
+ PTW_LCM_OK => PTE_Check_Success (ext_ptw ),
125
+ PTW_LCM_CLR => PTE_Check_Success (ext_ptw '),
126
+ PTW_LCM_TRAP => {
127
+ if scisa . pte_cap_lc_datadep () == 0b1 then {
128
+ /*
129
+ * Continue translating, but add caveat
130
+ */
131
+ PTE_Check_Success (ext_ptw ')
132
+ } else {
133
+ /*
134
+ * Stop translating and raise a trap now
135
+ */
136
+ PTE_Check_Failure (ext_ptw ', EPTWF_CAP_ERR )
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ val checkPTEPermission_SC_caveat : Ext_PTE_Bits -> ext_ptw_scm
143
+ function checkPTEPermission_SC_caveat (e ) =
144
+ match (e . StoreCap (), e . StoreCap_Mod ()) {
145
+ (0b1 , _ ) => PTW_SCM_OK , /* Permitted */
146
+ (0b0 , 0b0 ) => PTW_SCM_TRAP , /* Forbidden, unmodified */
147
+ (0b0 , 0b1 ) => PTW_SCM_OK /* Forbidden, modified; see update_PTE_bits */
148
+ }
149
+
150
+ val checkPTEPermission_SC_caveat_datadep : (ext_ptw_scm , ext_ptw ) -> PTE_Check effect { rreg }
151
+ function checkPTEPermission_SC_caveat_datadep (scav , ext_ptw ) = {
152
+ match (scav ) {
153
+ PTW_SCM_OK => PTE_Check_Success (ext_ptw ),
154
+ PTW_SCM_TRAP => {
155
+ let ext_ptw ' = ext_ptw_join_scm (ext_ptw , scav );
156
+ if scisa . pte_cap_sc_datadep () == 0b1 then {
157
+ PTE_Check_Success (ext_ptw ')
158
+ } else {
159
+ PTE_Check_Failure (ext_ptw ', EPTWF_CAP_ERR )
160
+ }
161
+ }
162
+ }
163
+ }
164
+
120
165
function checkPTEPermission (ac : AccessType (ext_access_type ), priv : Privilege , mxr : bool , do_sum : bool , p : PTE_Bits , ext : extPte , ext_ptw : ext_ptw ) -> PTE_Check = {
121
166
/*
122
167
* Although in many cases MXR doesn't make sense for capabilities, we honour
@@ -130,7 +175,7 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
130
175
*
131
176
* 3. It's simpler to implement yet still safe (LC is unaffected by MXR).
132
177
*/
133
- let base_succ : bool =
178
+ let succ : bool =
134
179
match (ac , priv ) {
135
180
(Read (_ ), User ) => p . U () == 0b1 & (p . R () == 0b1 | (p . X () == 0b1 & mxr )),
136
181
(Write (_ ), User ) => p . U () == 0b1 & p . W () == 0b1 ,
@@ -145,27 +190,67 @@ function checkPTEPermission(ac : AccessType(ext_access_type), priv : Privilege,
145
190
(_, Machine ) => internal_error ("m-mode mem perm check" )
146
191
};
147
192
193
+ let res : PTE_Check =
194
+ if succ
195
+ then PTE_Check_Success (ext_ptw )
196
+ else PTE_Check_Failure (ext_ptw , EPTWF_NO_PERM );
197
+
148
198
let e = Mk_Ext_PTE_Bits (ext );
199
+
200
+ /* And now it's time for a little (manual, expanded) Either-monadic logic. */
201
+
202
+ /*
203
+ * Check for invalid modifiers
204
+ */
205
+ let res : PTE_Check =
206
+ match res {
207
+ PTE_Check_Failure (_, _ ) => res ,
208
+ PTE_Check_Success (_ ) =>
209
+ if scisa . pte_cap_lsmod () == 0b0 &
210
+ ~(e . StoreCap_Mod () == 0b0 &
211
+ e . LoadCap_Mod () == 0b0 &
212
+ e . LoadCap_Gen () == 0b0 )
213
+ then PTE_Check_Failure (ext_ptw , EPTWF_INVALID )
214
+ else res
215
+ };
216
+
217
+ /*
218
+ * Check for store-side caveats, which may force a fault if data-independent
219
+ */
149
220
let scav = checkPTEPermission_SC_caveat (e );
221
+ let res : PTE_Check =
222
+ match res {
223
+ PTE_Check_Failure (_, _ ) => res ,
224
+ PTE_Check_Success (ext_ptw ) => match ac {
225
+ Execute () => res ,
226
+ Read (_ ) => res ,
227
+ Write (Data ) => res ,
228
+ ReadWrite (_, Data ) => res ,
229
+
230
+ ReadWrite (_, Cap ) => checkPTEPermission_SC_caveat_datadep (scav , ext_ptw ),
231
+ Write (Cap ) => checkPTEPermission_SC_caveat_datadep (scav , ext_ptw )
232
+ }
233
+ };
234
+
235
+ /*
236
+ * Now do load-side caveats, which may also force a fault if data-dependent
237
+ */
150
238
let lcav = checkPTEPermission_LC_caveat (p , e );
151
- let (succ , ext_ptw ') : (bool , ext_ptw ) =
152
- match (base_succ , ac ) {
153
- /* Base translation exceptions take priority over CHERI exceptions */
154
- (false , _ ) => (false , init_ext_ptw ),
155
-
156
- (true , Read (Cap )) => (true , ext_ptw_join_lcm (ext_ptw , lcav )),
157
- (true , Write (Cap )) => (true , ext_ptw_join_scm (ext_ptw , scav )),
158
- (true , ReadWrite (Data , Cap )) => (true , ext_ptw_join_scm (ext_ptw , scav )),
159
- (true , ReadWrite (Cap , Data )) => (true , ext_ptw_join_lcm (ext_ptw , lcav )),
160
- (true , ReadWrite (Cap , Cap )) => (true , ext_ptw_join_scm (ext_ptw_join_lcm (ext_ptw , lcav ), scav )),
161
-
162
- (true , Read (Data )) => (true , ext_ptw ),
163
- (true , Write (Data )) => (true , ext_ptw ),
164
- (true , ReadWrite (Data , Data )) => (true , ext_ptw ),
165
- (true , Execute ()) => (true , ext_ptw )
166
- };
239
+ let res : PTE_Check =
240
+ match res {
241
+ PTE_Check_Failure (_, _ ) => res ,
242
+ PTE_Check_Success (ext_ptw ) => match ac {
243
+ Execute () => res ,
244
+ Write (_ ) => res ,
245
+ Read (Data ) => res ,
246
+ ReadWrite (Data , _ ) => res ,
247
+
248
+ Read (Cap ) => checkPTEPermission_LC_caveat_datadep (lcav , ext_ptw ),
249
+ ReadWrite (Cap , _ ) => checkPTEPermission_LC_caveat_datadep (lcav , ext_ptw )
250
+ }
251
+ };
167
252
168
- if succ then PTE_Check_Success ( ext_ptw ') else PTE_Check_Failure ( ext_ptw ')
253
+ res
169
254
}
170
255
171
256
function update_PTE_Bits (p : PTE_Bits , a : AccessType (ext_access_type ), ext : extPte ) -> option ((PTE_Bits , extPte )) = {
0 commit comments