@@ -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