-
Notifications
You must be signed in to change notification settings - Fork 0
/
Tcb_D.thy
320 lines (275 loc) · 14.1 KB
/
Tcb_D.thy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
(*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: GPL-2.0-only
*)
(*
* Operations on thread control blocks.
*)
theory Tcb_D
imports Invocations_D CSpace_D
begin
definition cdl_update_cnode_cap_data :: "cdl_cap \<Rightarrow> word32 \<Rightarrow> cdl_cap"
where "cdl_update_cnode_cap_data cap data \<equiv>
case cap of cdl_cap.CNodeCap oid _ _ sz \<Rightarrow> if data\<noteq>0 then
(let reserved_bits = 3; guard_bits = 18; guard_size_bits = 5; new_guard_size = unat ((data >> reserved_bits) && mask guard_size_bits);
new_guard =
(data >> reserved_bits + guard_size_bits) && mask (min (unat ((data >> reserved_bits) && mask guard_size_bits)) guard_bits)
in CNodeCap oid new_guard new_guard_size sz)
else cap
| _ \<Rightarrow> cap"
definition cdl_same_arch_obj_as :: "cdl_cap \<Rightarrow> cdl_cap \<Rightarrow> bool"
where "cdl_same_arch_obj_as capa capb \<equiv>
case capa of AsidPoolCap x _ \<Rightarrow> (
case capb of AsidPoolCap y _ \<Rightarrow> y = x
| _ \<Rightarrow> False)
| AsidControlCap \<Rightarrow> (
case capb of AsidControlCap \<Rightarrow> True
| _ \<Rightarrow> False)
| FrameCap dev ra _ sa _ _ \<Rightarrow> (
case capb of FrameCap dev' rb _ sb _ _ \<Rightarrow> rb = ra \<and> sb = sa \<and> dev = dev'
| _ \<Rightarrow> False)
| cdl_cap.PageTableCap a _ _ \<Rightarrow> (
case capb of cdl_cap.PageTableCap b _ _ \<Rightarrow> b = a
| _ \<Rightarrow> False)
| cdl_cap.PageDirectoryCap a _ _ \<Rightarrow> (
case capb of cdl_cap.PageDirectoryCap b _ _ \<Rightarrow> b = a
| _ \<Rightarrow> False)
| _ \<Rightarrow> False"
definition
decode_tcb_invocation :: "cdl_cap \<Rightarrow> cdl_cap_ref \<Rightarrow> (cdl_cap \<times> cdl_cap_ref) list \<Rightarrow>
cdl_tcb_intent \<Rightarrow> cdl_tcb_invocation except_monad"
where
"decode_tcb_invocation target slot caps intent \<equiv> case intent of
\<comment> \<open>Read another thread's registers.\<close>
TcbReadRegistersIntent suspend flags count \<Rightarrow>
returnOk (ReadRegisters (cap_object target) suspend 0 0) \<sqinter> throw
\<comment> \<open>Write another thread's registers.\<close>
| TcbWriteRegistersIntent resume flags count regs \<Rightarrow>
returnOk (WriteRegisters (cap_object target) resume [0] 0) \<sqinter> throw
\<comment> \<open>Copy registers from one thread to another.\<close>
| TcbCopyRegistersIntent suspend_source resume_target f1 f2 f3 \<Rightarrow>
doE
(source_cap, _) \<leftarrow> throw_on_none $ get_index caps 0;
source_tcb \<leftarrow> (
case source_cap of
TcbCap x \<Rightarrow> returnOk x
| _ \<Rightarrow> throw);
target_tcb \<leftarrow> returnOk $ cap_object target;
returnOk (CopyRegisters target_tcb source_tcb suspend_source resume_target f1 f2 0)
odE \<sqinter> throw
\<comment> \<open>Suspend the target thread.\<close>
| TcbSuspendIntent \<Rightarrow>
returnOk (Suspend (cap_object target)) \<sqinter> throw
\<comment> \<open>Resume the target thread.\<close>
| TcbResumeIntent \<Rightarrow>
returnOk (Resume (cap_object target)) \<sqinter> throw
\<comment> \<open>Configure: target, fault_ep, mcp, priority, cspace_root_data, vspace_root_data, buffer\<close>
| TcbConfigureIntent fault_ep cspace_root_data vspace_root_data buffer \<Rightarrow>
doE
cspace_root \<leftarrow> throw_on_none $ get_index caps 0;
vspace_root \<leftarrow> throw_on_none $ get_index caps 1;
buffer_frame \<leftarrow> throw_on_none $ get_index caps 2;
cspace_root_cap_ref \<leftarrow> returnOk $ (cdl_update_cnode_cap_data (fst cspace_root) cspace_root_data,snd cspace_root);
vspace_root_cap_ref \<leftarrow> returnOk $ vspace_root;
buffer_frame_opt \<leftarrow> returnOk $ (if (buffer \<noteq> 0) then Some (reset_mem_mapping (fst buffer_frame), snd buffer_frame) else None);
returnOk (ThreadControl (cap_object target) slot (Some fault_ep)
(Some cspace_root_cap_ref) (Some vspace_root_cap_ref) (buffer_frame_opt))
odE \<sqinter> throw
\<comment> \<open>Modify a thread's maximum control priority.\<close>
| TcbSetMCPriorityIntent mcp \<Rightarrow>
doE
auth_cap \<leftarrow> throw_on_none $ get_index caps 0;
returnOk (ThreadControl (cap_object target) slot None None None None)
odE \<sqinter> throw
\<comment> \<open>Modify a thread's priority.\<close>
| TcbSetPriorityIntent priority \<Rightarrow>
doE
auth_cap \<leftarrow> throw_on_none $ get_index caps 0;
returnOk (ThreadControl (cap_object target) slot None None None None)
odE \<sqinter> throw
\<comment> \<open>Modify a thread's mcp and priority at the same time.\<close>
| TcbSetSchedParamsIntent mcp priority \<Rightarrow>
doE
auth_cap \<leftarrow> throw_on_none $ get_index caps 0;
returnOk (ThreadControl (cap_object target) slot None None None None)
odE \<sqinter> throw
\<comment> \<open>Modify a thread's IPC buffer.\<close>
| TcbSetIPCBufferIntent buffer \<Rightarrow>
doE
buffer_frame \<leftarrow> throw_on_none $ get_index caps 0;
buffer_frame_opt \<leftarrow> returnOk $ (if (buffer \<noteq> 0) then Some (reset_mem_mapping (fst buffer_frame), snd buffer_frame) else None);
returnOk (ThreadControl (cap_object target) slot None None None buffer_frame_opt)
odE \<sqinter> throw
\<comment> \<open>Update the various spaces (CSpace/VSpace) of a thread.\<close>
| TcbSetSpaceIntent fault_ep cspace_root_data vspace_root_data \<Rightarrow>
doE
cspace_root \<leftarrow> throw_on_none $ get_index caps 0;
vspace_root \<leftarrow> throw_on_none $ get_index caps 1;
cspace_root_cap_ref \<leftarrow> returnOk $ (cdl_update_cnode_cap_data (fst cspace_root) cspace_root_data,snd cspace_root);
vspace_root_cap_ref \<leftarrow> returnOk $ vspace_root;
returnOk (ThreadControl (cap_object target) slot (Some fault_ep)
(Some cspace_root_cap_ref) (Some vspace_root_cap_ref) None)
odE \<sqinter> throw
| TcbBindNTFNIntent \<Rightarrow> doE
(ntfn_cap, _) \<leftarrow> throw_on_none $ get_index caps 0;
returnOk (NotificationControl (cap_object target) (Some (cap_object ntfn_cap)))
odE \<sqinter> throw
| TcbUnbindNTFNIntent \<Rightarrow> returnOk (NotificationControl (cap_object target) None) \<sqinter> throw
| TCBSetTLSBaseIntent \<Rightarrow> returnOk (SetTLSBase (cap_object target)) \<sqinter> throw
"
(* Delete the given slot of a TCB. *)
definition
tcb_empty_thread_slot :: "cdl_object_id \<Rightarrow> cdl_cnode_index \<Rightarrow> unit preempt_monad"
where
"tcb_empty_thread_slot target_tcb target_slot \<equiv> doE
cap \<leftarrow> liftE $ get_cap (target_tcb,target_slot);
whenE (cap \<noteq> NullCap) $
delete_cap (target_tcb, target_slot)
odE"
(* Update the given slot of a TCB with a new cap, delete the previous
* capability that was in the slot. *)
definition
tcb_update_thread_slot :: "cdl_object_id \<Rightarrow> cdl_cap_ref \<Rightarrow> cdl_cnode_index \<Rightarrow> (cdl_cap \<times> cdl_cap_ref) \<Rightarrow> unit preempt_monad"
where
"tcb_update_thread_slot target_tcb tcb_cap_slot target_slot pcap \<equiv>
liftE (do
thread_cap \<leftarrow> get_cap tcb_cap_slot;
when (thread_cap = TcbCap target_tcb)
(insert_cap_child (fst pcap) (snd pcap) (target_tcb, target_slot)
\<sqinter> insert_cap_sibling (fst pcap) (snd pcap) (target_tcb,target_slot))
od)"
(* Update a thread's CSpace root. *)
definition
tcb_update_cspace_root :: "cdl_object_id \<Rightarrow> cdl_cap_ref \<Rightarrow> cdl_cap \<times> cdl_cap_ref \<Rightarrow> unit preempt_monad"
where
"tcb_update_cspace_root target_tcb tcb_cap_ref croot \<equiv>
doE
tcb_empty_thread_slot target_tcb tcb_cspace_slot;
src_cap \<leftarrow> liftE $ get_cap (snd croot);
whenE (is_cnode_cap src_cap \<and> (cap_object src_cap = cap_object (fst croot)))
$ tcb_update_thread_slot target_tcb tcb_cap_ref tcb_cspace_slot croot
odE"
(* Update a thread's VSpace root. *)
definition
tcb_update_vspace_root :: "cdl_object_id \<Rightarrow> cdl_cap_ref \<Rightarrow> (cdl_cap \<times> cdl_cap_ref) \<Rightarrow> unit preempt_monad"
where
"tcb_update_vspace_root target_tcb tcb_cap_ref vroot \<equiv>
doE
tcb_empty_thread_slot target_tcb tcb_vspace_slot;
src_cap \<leftarrow> liftE $ get_cap (snd vroot);
whenE (cdl_same_arch_obj_as (fst vroot) src_cap)
$ tcb_update_thread_slot target_tcb tcb_cap_ref tcb_vspace_slot vroot
odE"
(* Modify the TCB's intent to indicate an error during decode. *)
definition
mark_tcb_intent_error :: "cdl_object_id \<Rightarrow> bool \<Rightarrow> unit k_monad"
where
"mark_tcb_intent_error target_tcb has_error \<equiv>
update_thread target_tcb (\<lambda>t. (t\<lparr>cdl_tcb_intent := (cdl_tcb_intent t)\<lparr>cdl_intent_error := has_error\<rparr>\<rparr>))"
(* Update a thread's IPC buffer. *)
definition
tcb_update_ipc_buffer :: "cdl_object_id \<Rightarrow> cdl_cap_ref \<Rightarrow> (cdl_cap \<times> cdl_cap_ref) \<Rightarrow> unit preempt_monad"
where
"tcb_update_ipc_buffer target_tcb tcb_cap_ref ipc_buffer \<equiv>
doE
tcb_empty_thread_slot target_tcb tcb_ipcbuffer_slot;
liftE $ corrupt_tcb_intent target_tcb;
src_cap \<leftarrow> liftE $ get_cap (snd ipc_buffer);
whenE (cdl_same_arch_obj_as (fst ipc_buffer) src_cap)
$ tcb_update_thread_slot target_tcb tcb_cap_ref tcb_ipcbuffer_slot ipc_buffer
odE
"
(* Resume a thread, aborting any pending operation, and revoking
* any incoming reply caps. *)
definition
restart :: "cdl_object_id \<Rightarrow> unit k_monad"
where
"restart target_tcb \<equiv>
do
cap \<leftarrow> KHeap_D.get_cap (target_tcb,tcb_pending_op_slot);
when (cap \<noteq> RestartCap \<and> cap\<noteq> RunningCap)
(do
CSpace_D.cancel_ipc target_tcb;
KHeap_D.set_cap (target_tcb,tcb_replycap_slot) (cdl_cap.MasterReplyCap target_tcb);
KHeap_D.set_cap (target_tcb,tcb_pending_op_slot) (cdl_cap.RestartCap)
od)
od"
(* Suspend a thread, aborting any pending operation, and revoking
* any incoming reply caps. *)
definition
suspend :: "cdl_object_id \<Rightarrow> unit k_monad"
where
"suspend target_tcb \<equiv> CSpace_D.cancel_ipc target_tcb >>= K (KHeap_D.set_cap (target_tcb,tcb_pending_op_slot) cdl_cap.NullCap)"
definition
bind_notification :: "cdl_object_id \<Rightarrow> cdl_object_id \<Rightarrow> unit k_monad"
where
"bind_notification tcb_id ntfn_id \<equiv> set_cap (tcb_id, tcb_boundntfn_slot) (BoundNotificationCap ntfn_id)"
definition
invoke_tcb :: "cdl_tcb_invocation \<Rightarrow> unit preempt_monad"
where
"invoke_tcb params \<equiv> case params of
\<comment> \<open>Modify a thread's registers.\<close>
WriteRegisters target_tcb resume _ _ \<Rightarrow>
liftE $
do
corrupt_tcb_intent target_tcb;
when resume $ restart target_tcb
od
\<comment> \<open>Read a thread's registers.\<close>
| ReadRegisters src_tcb _ _ _ \<Rightarrow>
liftE $ suspend src_tcb \<sqinter> return ()
\<comment> \<open>Copy registers from one thread to another\<close>
| CopyRegisters target_tcb source_tcb _ _ _ _ _ \<Rightarrow>
liftE $
do
suspend source_tcb \<sqinter> return ();
restart target_tcb \<sqinter> return ();
corrupt_tcb_intent target_tcb
od
\<comment> \<open>Suspend this thread.\<close>
| Suspend target_tcb \<Rightarrow>
liftE $ suspend target_tcb \<sqinter> return ()
\<comment> \<open>Resume this thread.\<close>
| Resume target_tcb \<Rightarrow>
liftE $ restart target_tcb
\<comment> \<open>Update a thread's options.\<close>
| ThreadControl target_tcb tcb_cap_slot faultep croot vroot ipc_buffer \<Rightarrow>
doE
case faultep of
Some x \<Rightarrow> liftE $ update_thread target_tcb (\<lambda>tcb. tcb\<lparr>cdl_tcb_fault_endpoint := x\<rparr>)
| None \<Rightarrow> returnOk ();
\<comment> \<open>Possibly update CSpace\<close>
case croot of
Some x \<Rightarrow> tcb_update_cspace_root target_tcb tcb_cap_slot x
| None \<Rightarrow> returnOk ();
\<comment> \<open>Possibly update VSpace\<close>
case vroot of
Some x \<Rightarrow> tcb_update_vspace_root target_tcb tcb_cap_slot x
| None \<Rightarrow> returnOk ();
\<comment> \<open>Possibly update Ipc Buffer\<close>
case ipc_buffer of
Some x \<Rightarrow> tcb_update_ipc_buffer target_tcb tcb_cap_slot x
| None \<Rightarrow> (returnOk () \<sqinter> (doE tcb_empty_thread_slot target_tcb tcb_ipcbuffer_slot;
liftE $ corrupt_tcb_intent target_tcb odE))
odE
| NotificationControl tcb ntfn \<Rightarrow>
liftE $ (case ntfn of
Some ntfn_id \<Rightarrow> bind_notification tcb ntfn_id
| None \<Rightarrow> unbind_notification tcb)
| SetTLSBase tcb \<Rightarrow> liftE $ corrupt_tcb_intent tcb"
definition
decode_domain_invocation :: "(cdl_cap \<times> cdl_cap_ref) list \<Rightarrow> cdl_domain_intent \<Rightarrow> cdl_domain_invocation except_monad"
where
"decode_domain_invocation caps intent \<equiv> case intent of
DomainSetIntent d \<Rightarrow> returnOk (SetDomain (cap_object (fst (hd caps))) d) \<sqinter> throw"
definition
set_domain :: "cdl_object_id \<Rightarrow> word8 \<Rightarrow> unit k_monad"
where
"set_domain tcb d \<equiv> update_thread tcb (\<lambda>t. (t\<lparr>cdl_tcb_domain := d \<rparr>))"
definition
invoke_domain :: "cdl_domain_invocation \<Rightarrow> unit preempt_monad"
where
"invoke_domain params \<equiv> case params of
SetDomain tcb d \<Rightarrow> liftE $ set_domain tcb d"
end