forked from seL4/l4v
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Structures_A.thy
702 lines (594 loc) · 24.4 KB
/
Structures_A.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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
(*
* Copyright 2014, General Dynamics C4 Systems
*
* SPDX-License-Identifier: GPL-2.0-only
*)
(*
The main architecture independent data types and type definitions in
the abstract model.
*)
chapter "Basic Data Structures"
theory Structures_A
imports
Arch_Structs_A
"ExecSpec.MachineExports"
begin
context begin interpretation Arch .
requalify_types
aobject_type
arch_cap
vm_rights
arch_kernel_obj
arch_state
arch_tcb
aa_type
requalify_consts
acap_rights
acap_rights_update
arch_kobj_size
arch_obj_size
aobj_ref
asid_high_bits
asid_low_bits
arch_is_frame_type
badge_bits
default_arch_tcb
arch_tcb_context_get
arch_tcb_context_set
arch_tcb_set_registers
arch_tcb_get_registers
cte_level_bits
tcb_bits
endpoint_bits
ntfn_bits
aa_type
untyped_min_bits
untyped_max_bits
msg_label_bits
end
text \<open>
User mode can request these objects to be created by retype:
\<close>
datatype apiobject_type =
Untyped
| TCBObject
| EndpointObject
| NotificationObject
| CapTableObject
| ArchObject aobject_type
definition
is_frame_type :: "apiobject_type \<Rightarrow> bool"
where
"is_frame_type obj \<equiv> case obj of
ArchObject aobj \<Rightarrow> arch_is_frame_type aobj
| _ \<Rightarrow> False"
text \<open>These allow more informative type signatures for IPC operations.\<close>
type_synonym badge = data
type_synonym msg_label = data
type_synonym message = data
text \<open>This type models refences to capability slots. The first element
of the tuple points to the object the capability is contained in. The second
element is the index of the slot inside a slot-containing object. The default
slot-containing object is a cnode, thus the name @{text cnode_index}.
\<close>
type_synonym cnode_index = "bool list"
type_synonym cslot_ptr = "obj_ref \<times> cnode_index"
text \<open>Capabilities. Capabilities represent explicit authority to perform some
action and are required for all system calls. Capabilities to Endpoint,
Notification, Thread and CNode objects allow manipulation of standard kernel
objects. Untyped capabilities allow the creation and removal of kernel objects
from a memory region. Reply capabilities allow sending a one-off message to
a thread waiting for a reply. IRQHandler and IRQControl caps allow a user to
configure the way interrupts on one or all IRQs are handled. Capabilities to
architecture-specific facilities are provided through the @{text arch_cap} type.
Null capabilities are the contents of empty capability slots; they confer no
authority and can be freely replaced. Zombie capabilities are stored when
the deletion of CNode and Thread objects is partially completed; they confer no
authority but cannot be replaced until the deletion is finished.
\<close>
datatype cap
= NullCap
| UntypedCap bool obj_ref nat nat
\<comment> \<open>device flag, pointer, size in bits (i.e. @{text "size = 2^bits"}) and freeIndex (i.e. @{text "freeRef = obj_ref + (freeIndex * 2^4)"})\<close>
| EndpointCap obj_ref badge cap_rights
| NotificationCap obj_ref badge cap_rights
| ReplyCap obj_ref bool cap_rights
| CNodeCap obj_ref nat "bool list"
\<comment> \<open>CNode ptr, number of bits translated, guard\<close>
| ThreadCap obj_ref
| DomainCap
| IRQControlCap
| IRQHandlerCap irq
| Zombie obj_ref "nat option" nat
\<comment> \<open>@{text "cnode ptr * nat + tcb or cspace ptr"}\<close>
| ArchObjectCap (the_arch_cap: arch_cap)
lemmas cap_cases =
cap.induct[where cap=cap and P="\<lambda>cap'. cap' = cap \<longrightarrow> P cap'" for cap P, simplified, rule_format]
lemmas cap_cases_asm =
cap.induct[where cap=cap and P="\<lambda>cap'. cap = cap' \<longrightarrow> P cap' \<longrightarrow> R" for P R cap,
simplified, rule_format, rotated -1]
text \<open>The CNode object is an array of capability slots. The domain of the
function will always be the set of boolean lists of some specific length.
Empty slots contain a Null capability.
\<close>
type_synonym cnode_contents = "cnode_index \<Rightarrow> cap option"
text \<open>Various access functions for the cap type are defined for
convenience.\<close>
definition
the_cnode_cap :: "cap \<Rightarrow> obj_ref \<times> nat \<times> bool list" where
"the_cnode_cap cap \<equiv>
case cap of
CNodeCap oref bits guard \<Rightarrow> (oref, bits, guard)"
definition
the_arch_cap :: "cap \<Rightarrow> arch_cap" where
"the_arch_cap cap \<equiv> case cap of ArchObjectCap a \<Rightarrow> a"
primrec (nonexhaustive)
cap_ep_badge :: "cap \<Rightarrow> badge"
where
"cap_ep_badge (EndpointCap _ badge _) = badge"
| "cap_ep_badge (NotificationCap _ badge _) = badge"
primrec (nonexhaustive)
cap_ep_ptr :: "cap \<Rightarrow> badge"
where
"cap_ep_ptr (EndpointCap obj_ref _ _) = obj_ref"
| "cap_ep_ptr (NotificationCap obj_ref _ _) = obj_ref"
definition
bits_of :: "cap \<Rightarrow> nat" where
"bits_of cap \<equiv> case cap of
UntypedCap _ _ bits _ \<Rightarrow> bits
| CNodeCap _ radix_bits _ \<Rightarrow> radix_bits"
definition
free_index_of :: "cap \<Rightarrow> nat" where
"free_index_of cap \<equiv> case cap of
UntypedCap _ _ _ free_index \<Rightarrow> free_index"
definition
is_reply_cap :: "cap \<Rightarrow> bool" where
"is_reply_cap cap \<equiv> case cap of ReplyCap _ m _ \<Rightarrow> \<not> m | _ \<Rightarrow> False"
definition
is_master_reply_cap :: "cap \<Rightarrow> bool" where
"is_master_reply_cap cap \<equiv> case cap of ReplyCap _ m _ \<Rightarrow> m | _ \<Rightarrow> False"
definition
is_zombie :: "cap \<Rightarrow> bool" where
"is_zombie cap \<equiv> case cap of Zombie _ _ _ \<Rightarrow> True | _ \<Rightarrow> False"
definition
is_arch_cap :: "cap \<Rightarrow> bool" where
"is_arch_cap cap \<equiv> case cap of ArchObjectCap _ \<Rightarrow> True | _ \<Rightarrow> False"
context
notes [[function_internals =true]]
begin
fun is_cnode_cap :: "cap \<Rightarrow> bool"
where
"is_cnode_cap (CNodeCap _ _ _) = True"
| "is_cnode_cap _ = False"
fun is_thread_cap :: "cap \<Rightarrow> bool"
where
"is_thread_cap (ThreadCap _) = True"
| "is_thread_cap _ = False"
fun is_domain_cap :: "cap \<Rightarrow> bool"
where
"is_domain_cap DomainCap = True"
| "is_domain_cap _ = False"
fun is_untyped_cap :: "cap \<Rightarrow> bool"
where
"is_untyped_cap (UntypedCap _ _ _ _) = True"
| "is_untyped_cap _ = False"
fun is_ep_cap :: "cap \<Rightarrow> bool"
where
"is_ep_cap (EndpointCap _ _ _) = True"
| "is_ep_cap _ = False"
fun is_ntfn_cap :: "cap \<Rightarrow> bool"
where
"is_ntfn_cap (NotificationCap _ _ _) = True"
| "is_ntfn_cap _ = False"
primrec (nonexhaustive)
cap_rights :: "cap \<Rightarrow> cap_rights"
where
"cap_rights (EndpointCap _ _ cr) = cr"
| "cap_rights (NotificationCap _ _ cr) = cr"
| "cap_rights (ReplyCap _ _ cr) = cr"
| "cap_rights (ArchObjectCap acap) = acap_rights acap"
end
text \<open>Various update functions for cap data common to various kinds of
cap are defined here.\<close>
definition
cap_rights_update :: "cap_rights \<Rightarrow> cap \<Rightarrow> cap" where
"cap_rights_update cr' cap \<equiv>
case cap of
EndpointCap oref badge cr \<Rightarrow> EndpointCap oref badge cr'
| NotificationCap oref badge cr
\<Rightarrow> NotificationCap oref badge (cr' - {AllowGrant, AllowGrantReply})
| ReplyCap t m cr \<Rightarrow> ReplyCap t m (cr' - {AllowRead, AllowGrantReply} \<union> {AllowWrite})
| ArchObjectCap acap \<Rightarrow> ArchObjectCap (acap_rights_update cr' acap)
| _ \<Rightarrow> cap"
definition
badge_update :: "badge \<Rightarrow> cap \<Rightarrow> cap" where
"badge_update data cap \<equiv>
case cap of
EndpointCap oref badge cr \<Rightarrow> EndpointCap oref (data && mask badge_bits) cr
| NotificationCap oref badge cr \<Rightarrow> NotificationCap oref (data && mask badge_bits) cr
| _ \<Rightarrow> cap"
definition
mask_cap :: "cap_rights \<Rightarrow> cap \<Rightarrow> cap" where
"mask_cap rights cap \<equiv> cap_rights_update (cap_rights cap \<inter> rights) cap"
section \<open>Message Info\<close>
text \<open>The message info is the first thing interpreted on a user system call
and determines the structure of the message the user thread is sending either to
another user or to a system service. It is also passed to user threads receiving
a message to indicate the structure of the message they have received. The
@{text mi_length} parameter is the number of data words in the body of the
message. The @{text mi_extra_caps} parameter is the number of caps to be passed
together with the message. The @{text mi_caps_unwrapped} parameter is a bitmask
allowing threads receiving a message to determine how extra capabilities were
transferred. The @{text mi_label} parameter is transferred directly from sender
to receiver as part of the message.
\<close>
datatype message_info =
MI (mi_length: length_type)
(mi_extra_caps: length_type)
(mi_caps_unwrapped: data)
(mi_label: msg_label)
text \<open>Message infos are encoded to or decoded from a data word.\<close>
primrec
message_info_to_data :: "message_info \<Rightarrow> data"
where
"message_info_to_data (MI len exc unw mlabel) =
(let
extra = exc << 7;
unwrapped = unw << 9;
label = mlabel << 12
in
label || extra || unwrapped || len)"
definition
data_to_message_info :: "data \<Rightarrow> message_info"
where
"data_to_message_info w \<equiv>
MI (let v = w && mask 7 in if v > 120 then 120 else v)
((w >> 7) && mask 2)
((w >> 9) && mask 3)
((w >> 12) && mask msg_label_bits)"
section \<open>Kernel Objects\<close>
text \<open>Endpoints are synchronous points of communication for threads. At any
time an endpoint may contain a queue of threads waiting to send, a queue of
threads waiting to receive or be idle. Whenever threads would be waiting to
send and receive simultaneously messages are transferred immediately.
\<close>
datatype endpoint
= IdleEP
| SendEP "obj_ref list"
| RecvEP "obj_ref list"
text \<open>Notifications are sets of binary semaphores (stored in the
\emph{badge word}). Unlike endpoints, threads may choose to block waiting to
receive, but not to send.\<close>
datatype ntfn
= IdleNtfn
| WaitingNtfn "obj_ref list"
| ActiveNtfn badge
record notification =
ntfn_obj :: ntfn
ntfn_bound_tcb :: "obj_ref option"
definition
default_ep :: endpoint where
"default_ep \<equiv> IdleEP"
definition
default_ntfn :: ntfn where
"default_ntfn \<equiv> IdleNtfn"
definition
default_notification :: notification where
"default_notification \<equiv> \<lparr>
ntfn_obj = default_ntfn,
ntfn_bound_tcb = None \<rparr>"
text \<open>Thread Control Blocks are the in-kernel representation of a thread.
Threads which can execute are either in the Running state for normal execution,
in the Restart state if their last operation has not completed yet or in the
IdleThreadState for the unique system idle thread. Threads can also be blocked
waiting for any of the different kinds of system messages. The Inactive state
indicates that the TCB is not currently used by a running thread.
TCBs also contain some special-purpose capability slots. The CTable slot is a
capability to a CNode through which the thread accesses capabilities with which
to perform system calls. The VTable slot is a capability to a virtual address
space (an architecture-specific capability type) in which the thread runs. If
the thread has issued a Reply cap to another thread and is awaiting a reply,
that cap will have a "master" Reply cap as its parent in the Reply slot. The
Caller slot is used to initially store any Reply cap issued to this thread. The
IPCFrame slot stores a capability to a memory frame (an architecture-specific
capability type) through which messages will be sent and received.
If the thread has encountered a fault and is waiting to send it to its
supervisor the fault is stored in @{text tcb_fault}. The user register file is
stored in @{text tcb_context}, the pointer to the cap in the IPCFrame slot in
@{text tcb_ipc_buffer} and the identity of the Endpoint cap through which faults
are to be sent in @{text tcb_fault_handler}.
\<close>
record sender_payload =
sender_badge :: badge
sender_can_grant :: bool
sender_can_grant_reply :: bool
sender_is_call :: bool
record receiver_payload =
receiver_can_grant :: bool
datatype thread_state
= Running
| Inactive
| Restart
| BlockedOnReceive obj_ref receiver_payload
| BlockedOnSend obj_ref sender_payload
| BlockedOnReply
| BlockedOnNotification obj_ref
| IdleThreadState
type_synonym priority = word8
record tcb =
tcb_ctable :: cap
tcb_vtable :: cap
tcb_reply :: cap
tcb_caller :: cap
tcb_ipcframe :: cap
tcb_state :: thread_state
tcb_fault_handler :: cap_ref
tcb_ipc_buffer :: vspace_ref
tcb_fault :: "fault option"
tcb_bound_notification :: "obj_ref option"
tcb_mcpriority :: priority
tcb_arch :: arch_tcb (* arch_tcb must have a field for user context *)
text \<open>Determines whether a thread in a given state may be scheduled.\<close>
primrec
runnable :: "Structures_A.thread_state \<Rightarrow> bool"
where
"runnable (Running) = True"
| "runnable (Inactive) = False"
| "runnable (Restart) = True"
| "runnable (BlockedOnReceive x y) = False"
| "runnable (BlockedOnSend x y) = False"
| "runnable (BlockedOnNotification x) = False"
| "runnable (IdleThreadState) = False"
| "runnable (BlockedOnReply) = False"
definition
default_tcb :: tcb where
"default_tcb \<equiv> \<lparr>
tcb_ctable = NullCap,
tcb_vtable = NullCap,
tcb_reply = NullCap,
tcb_caller = NullCap,
tcb_ipcframe = NullCap,
tcb_state = Inactive,
tcb_fault_handler = to_bl (0::machine_word),
tcb_ipc_buffer = 0,
tcb_fault = None,
tcb_bound_notification = None,
tcb_mcpriority = minBound,
tcb_arch = default_arch_tcb\<rparr>"
text \<open>
All kernel objects are CNodes, TCBs, Endpoints, Notifications or architecture
specific.
\<close>
datatype kernel_object
= CNode nat cnode_contents \<comment> \<open>size in bits, and contents\<close>
| TCB tcb
| Endpoint endpoint
| Notification notification
| ArchObj (the_arch_obj: arch_kernel_obj)
lemmas kernel_object_cases =
kernel_object.induct[where kernel_object=x and P="\<lambda>x'. x = x' \<longrightarrow> P x'" for x P, simplified, rule_format]
lemmas kernel_object_cases_asm =
kernel_object.induct[where kernel_object=x and P="\<lambda>x'. x = x' \<longrightarrow> P x' \<longrightarrow> R" for P R x,
simplified, rule_format, rotated -1]
definition aobj_of :: "kernel_object \<Rightarrow> arch_kernel_obj option"
where
"aobj_of ko \<equiv> case ko of ArchObj aobj \<Rightarrow> Some aobj | _ \<Rightarrow> None"
text \<open>Checks whether a cnode's contents are well-formed.\<close>
definition
well_formed_cnode_n :: "nat \<Rightarrow> cnode_contents \<Rightarrow> bool" where
"well_formed_cnode_n n \<equiv> \<lambda>cs. dom cs = {x. length x = n}"
primrec
obj_bits :: "kernel_object \<Rightarrow> nat"
where
"obj_bits (CNode sz cs) = cte_level_bits + sz"
| "obj_bits (TCB t) = tcb_bits"
| "obj_bits (Endpoint ep) = endpoint_bits"
| "obj_bits (Notification ntfn) = ntfn_bits"
| "obj_bits (ArchObj ao) = arch_kobj_size ao"
primrec (nonexhaustive)
obj_size :: "cap \<Rightarrow> machine_word"
where
"obj_size NullCap = 0"
| "obj_size (UntypedCap dev r bits f) = 1 << bits"
| "obj_size (EndpointCap r b R) = 1 << obj_bits (Endpoint undefined)"
| "obj_size (NotificationCap r b R) = 1 << obj_bits (Notification undefined)"
| "obj_size (CNodeCap r bits g) = 1 << (cte_level_bits + bits)"
| "obj_size (ThreadCap r) = 1 << obj_bits (TCB undefined)"
| "obj_size (Zombie r zb n) = (case zb of None \<Rightarrow> 1 << obj_bits (TCB undefined)
| Some n \<Rightarrow> 1 << (cte_level_bits + n))"
| "obj_size (ArchObjectCap a) = 1 << arch_obj_size a"
text \<open>Object types:\<close>
datatype a_type =
ATCB
| AEndpoint
| ANTFN
| ACapTable nat
| AGarbage nat \<comment> \<open>number of bytes of garbage\<close>
| AArch aa_type
definition
a_type :: "kernel_object \<Rightarrow> a_type"
where
"a_type ob \<equiv> case ob of
CNode sz cspace \<Rightarrow> if well_formed_cnode_n sz cspace
then ACapTable sz else AGarbage (cte_level_bits + sz)
| TCB tcb \<Rightarrow> ATCB
| Endpoint endpoint \<Rightarrow> AEndpoint
| Notification notification \<Rightarrow> ANTFN
| ArchObj ao \<Rightarrow> AArch (aa_type ao)"
section \<open>Kernel State\<close>
text \<open>The kernel's heap is a partial function containing kernel objects.\<close>
type_synonym kheap = "obj_ref \<Rightarrow> kernel_object option"
text \<open>
Capabilities are created either by cloning an existing capability or by creating
a subordinate capability from it. This results in a capability derivation tree
or CDT. The kernel provides a Revoke operation which deletes all capabilities
derived from one particular capability. To support this, the kernel stores the
CDT explicitly. It is here stored as a tree, a partial mapping from
capability slots to parent capability slots.
\<close>
type_synonym cdt = "cslot_ptr \<Rightarrow> cslot_ptr option"
datatype irq_state =
IRQInactive
| IRQSignal
| IRQTimer
| IRQReserved
text \<open>The kernel state includes a heap, a capability derivation tree
(CDT), a bitmap used to determine if a capability is the original
capability to that object, a pointer to the current thread, a pointer
to the system idle thread, the state of the underlying machine,
per-irq pointers to cnodes (each containing one notification through which
interrupts are delivered), an array recording which
interrupts are used for which purpose, and the state of the
architecture-specific kernel module.
Note: for each irq, @{text "interrupt_irq_node irq"} points to a cnode which
can contain the notification cap through which interrupts are delivered. In
C, this all lives in a single array. In the abstract spec though, to prove
security, we can't have a single object accessible by everyone. Hence the need
to separate irq handlers.
\<close>
record abstract_state =
kheap :: kheap
cdt :: cdt
is_original_cap :: "cslot_ptr \<Rightarrow> bool"
cur_thread :: obj_ref
idle_thread :: obj_ref
machine_state :: machine_state
interrupt_irq_node :: "irq \<Rightarrow> obj_ref"
interrupt_states :: "irq \<Rightarrow> irq_state"
arch_state :: arch_state
text \<open>The following record extends the abstract kernel state with extra
state of type @{typ "'a"}. The specification operates over states of
this extended type. By choosing an appropriate concrete type for @{typ "'a"}
we may obtain different \emph{instantiations} of the kernel specifications
at differing levels of abstraction. See \autoref{c:ext-spec} for further
information.
\<close>
record 'a state = abstract_state + exst :: 'a
section \<open>Helper functions\<close>
text \<open>This wrapper lifts monadic operations on the underlying machine state to
monadic operations on the kernel state.\<close>
definition
do_machine_op :: "(machine_state, 'a) nondet_monad \<Rightarrow> ('z state, 'a) nondet_monad"
where
"do_machine_op mop \<equiv> do
ms \<leftarrow> gets machine_state;
(r, ms') \<leftarrow> select_f (mop ms);
modify (\<lambda>state. state \<lparr> machine_state := ms' \<rparr>);
return r
od"
text \<open>This function generates the cnode indices used when addressing the
capability slots within a TCB.
\<close>
definition
tcb_cnode_index :: "nat \<Rightarrow> cnode_index" where
"tcb_cnode_index n \<equiv> to_bl (of_nat n :: 3 word)"
text \<open>Zombie capabilities store the bit size of the CNode cap they were
created from or None if they were created from a TCB cap. This function
decodes the bit-length of cnode indices into the relevant kernel objects.
\<close>
definition
zombie_cte_bits :: "nat option \<Rightarrow> nat" where
"zombie_cte_bits N \<equiv> case N of Some n \<Rightarrow> n | None \<Rightarrow> 3"
lemma zombie_cte_bits_simps[simp]:
"zombie_cte_bits (Some n) = n"
"zombie_cte_bits None = 3"
by (simp add: zombie_cte_bits_def)+
text \<open>The first capability slot of the relevant kernel object.\<close>
primrec (nonexhaustive)
first_cslot_of :: "cap \<Rightarrow> cslot_ptr"
where
"first_cslot_of (ThreadCap oref) = (oref, tcb_cnode_index 0)"
| "first_cslot_of (CNodeCap oref bits g) = (oref, replicate bits False)"
| "first_cslot_of (Zombie oref bits n) = (oref, replicate (zombie_cte_bits bits) False)"
text \<open>The set of all objects referenced by a capability.\<close>
primrec
obj_refs :: "cap \<Rightarrow> obj_ref set"
where
"obj_refs NullCap = {}"
| "obj_refs (ReplyCap r m cr) = {}"
| "obj_refs IRQControlCap = {}"
| "obj_refs (IRQHandlerCap irq) = {}"
| "obj_refs (UntypedCap dev r s f) = {}"
| "obj_refs (CNodeCap r bits guard) = {r}"
| "obj_refs (EndpointCap r b cr) = {r}"
| "obj_refs (NotificationCap r b cr) = {r}"
| "obj_refs (ThreadCap r) = {r}"
| "obj_refs DomainCap = {}"
| "obj_refs (Zombie ptr b n) = {ptr}"
| "obj_refs (ArchObjectCap x) = set_option (aobj_ref x)"
text \<open>
The partial definition below is sometimes easier to work with.
It also provides cases for UntypedCap and ReplyCap which are not
true object references in the sense of the other caps.
\<close>
primrec (nonexhaustive)
obj_ref_of :: "cap \<Rightarrow> obj_ref"
where
"obj_ref_of (UntypedCap dev r s f) = r"
| "obj_ref_of (ReplyCap r m cr) = r"
| "obj_ref_of (CNodeCap r bits guard) = r"
| "obj_ref_of (EndpointCap r b cr) = r"
| "obj_ref_of (NotificationCap r b cr) = r"
| "obj_ref_of (ThreadCap r) = r"
| "obj_ref_of (Zombie ptr b n) = ptr"
| "obj_ref_of (ArchObjectCap x) = the (aobj_ref x)"
primrec (nonexhaustive)
cap_bits_untyped :: "cap \<Rightarrow> nat"
where
"cap_bits_untyped (UntypedCap dev r s f) = s"
definition tcb_cnode_map :: "tcb \<Rightarrow> cnode_index \<Rightarrow> cap option"
where
"tcb_cnode_map tcb \<equiv>
[tcb_cnode_index 0 \<mapsto> tcb_ctable tcb,
tcb_cnode_index 1 \<mapsto> tcb_vtable tcb,
tcb_cnode_index 2 \<mapsto> tcb_reply tcb,
tcb_cnode_index 3 \<mapsto> tcb_caller tcb,
tcb_cnode_index 4 \<mapsto> tcb_ipcframe tcb]"
definition cap_of :: "kernel_object \<Rightarrow> cnode_index \<Rightarrow> cap option"
where
"cap_of kobj \<equiv> case kobj of CNode _ cs \<Rightarrow> cs | TCB tcb \<Rightarrow> tcb_cnode_map tcb | _ \<Rightarrow> Map.empty"
text \<open>The set of all caps contained in a kernel object.\<close>
definition
caps_of :: "kernel_object \<Rightarrow> cap set" where
"caps_of kobj \<equiv> ran (cap_of kobj)"
section "Cap transfers"
record captransfer =
ct_receive_root :: cap_ref
ct_receive_index :: cap_ref
ct_receive_depth :: data
text \<open>A thread's IPC buffer capability must be to a page that is capable of
containing the IPC buffer without the end of the buffer spilling into another
page.\<close>
definition cap_transfer_data_size :: nat
where
"cap_transfer_data_size \<equiv> 3"
definition msg_max_length :: nat
where
"msg_max_length \<equiv> 120"
definition msg_max_extra_caps :: nat
where
"msg_max_extra_caps \<equiv> 3"
definition max_ipc_length :: nat
where
"max_ipc_length \<equiv> cap_transfer_data_size + msg_max_length + msg_max_extra_caps + 2"
definition msg_align_bits :: nat
where
"msg_align_bits \<equiv> word_size_bits + (LEAST n. max_ipc_length \<le> 2 ^ n)"
lemma msg_align_bits':
"msg_align_bits = word_size_bits + 7"
proof -
have "(LEAST n. (cap_transfer_data_size + msg_max_length + msg_max_extra_caps + 2) \<le> 2 ^ n) = 7"
proof (rule Least_equality)
show "(cap_transfer_data_size + msg_max_length + msg_max_extra_caps + 2) \<le> 2 ^ 7"
by (simp add: cap_transfer_data_size_def msg_max_length_def msg_max_extra_caps_def)
next
fix y
assume "(cap_transfer_data_size + msg_max_length + msg_max_extra_caps + 2) \<le> 2 ^ y"
hence "(2 :: nat) ^ 7 \<le> 2 ^ y"
by (simp add: cap_transfer_data_size_def msg_max_length_def msg_max_extra_caps_def)
thus "7 \<le> y"
by (rule power_le_imp_le_exp [rotated], simp)
qed
thus ?thesis unfolding msg_align_bits_def max_ipc_length_def by simp
qed
end