-
Notifications
You must be signed in to change notification settings - Fork 108
/
CNode_IF.thy
786 lines (685 loc) · 33.3 KB
/
CNode_IF.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
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
(*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: GPL-2.0-only
*)
theory CNode_IF
imports ArchFinalCaps
begin
lemma cap_fault_on_failure_rev:
"reads_equiv_valid_inv A aag P m
\<Longrightarrow> reads_equiv_valid_inv A aag P (cap_fault_on_failure cptr rp m)"
unfolding cap_fault_on_failure_def handleE'_def
by (wp | wpc | simp add: o_def)+
lemma cap_fault_on_failure_rev_g:
"reads_respects_g aag l P m \<Longrightarrow> reads_respects_g aag l P (cap_fault_on_failure cptr rp m)"
unfolding cap_fault_on_failure_def handleE'_def
by (wp | wpc | simp add: o_def)+
definition gets_apply where
"gets_apply f x \<equiv>
do s \<leftarrow> get;
return ((f s) x)
od"
lemma gets_apply_ev:
"equiv_valid I A A (K (\<forall>s t. I s t \<and> A s t \<longrightarrow> (f s) x = (f t) x)) (gets_apply f x)"
apply (simp add: gets_apply_def get_def bind_def return_def)
apply (clarsimp simp: equiv_valid_def2 equiv_valid_2_def)
done
lemma gets_apply:
"gets f >>= (\<lambda>f. g (f x)) = gets_apply f x >>= g"
by (simp add: gets_apply_def gets_def)
lemma get_object_rev:
"reads_equiv_valid_inv A aag (\<lambda>s. aag_can_read aag oref) (get_object oref)"
apply (unfold get_object_def fun_app_def)
apply (subst gets_apply)
apply (wp gets_apply_ev | wp (once) hoare_drop_imps)+
apply (fastforce elim: reads_equivE equiv_forE)
done
lemma get_cap_rev:
"reads_equiv_valid_inv A aag (K (aag_can_read aag (fst slot))) (get_cap slot)"
unfolding get_cap_def
by (wp get_object_rev | wpc | simp add: split_def)+
declare if_weak_cong[cong]
lemma resolve_address_bits_spec_rev:
"reads_spec_equiv_valid_inv s A aag
(pas_refined aag and K (is_cnode_cap (fst ref) \<longrightarrow> is_subject aag (obj_ref_of (fst ref))))
(resolve_address_bits ref)"
proof(unfold resolve_address_bits_def, induct ref arbitrary: s rule: resolve_address_bits'.induct)
case (1 z cap' cref' s') show ?case
apply (subst resolve_address_bits'.simps)
apply (cases cap')
apply (simp_all add: drop_spec_ev throwError_ev_pre
cong: if_cong
split del: if_split)
apply (wp "1.hyps")
apply (assumption | simp add: in_monad | rule conjI)+
apply (wp get_cap_rev get_cap_wp whenE_throwError_wp)+
apply (auto simp: cte_wp_at_caps_of_state is_cap_simps cap_auth_conferred_def
dest: caps_of_state_pasObjectAbs_eq)
done
qed
lemma resolve_address_bits_rev:
"reads_equiv_valid_inv A aag
(pas_refined aag and K (is_cnode_cap (fst ref) \<longrightarrow> is_subject aag (obj_ref_of (fst ref))))
(resolve_address_bits ref)"
by (rule use_spec_ev[OF resolve_address_bits_spec_rev])
lemma lookup_slot_for_thread_rev:
"reads_equiv_valid_inv A aag (pas_refined aag and K (is_subject aag thread))
(lookup_slot_for_thread thread cptr)"
unfolding lookup_slot_for_thread_def fun_app_def
apply (rule gen_asm_ev)
apply (wp resolve_address_bits_rev gets_the_ev | simp)+
apply (rule conjI)
apply blast
apply (clarsimp simp: tcb.splits)
apply (erule (2) owns_thread_owns_cspace)
defer
apply (case_tac tcb_ctablea, simp_all)
done
lemma lookup_cap_and_slot_rev[wp]:
"reads_equiv_valid_inv A aag (pas_refined aag and K (is_subject aag thread))
(lookup_cap_and_slot thread cptr)"
unfolding lookup_cap_and_slot_def
by (wp lookup_slot_for_thread_rev lookup_slot_for_thread_authorised get_cap_rev
| simp add: split_def
| strengthen aag_can_read_self)+
lemmas lookup_cap_and_slot_reads_respects_g =
reads_respects_g_from_inv[OF lookup_cap_and_slot_rev lookup_cap_and_slot_inv]
lemma set_cap_reads_respects:
"reads_respects aag l (K (aag_can_read aag (fst slot))) (set_cap cap slot)"
by (wpsimp wp: set_object_reads_respects get_object_rev hoare_vcg_all_lift
simp: set_cap_def split_def)
lemma set_original_reads_respects:
"reads_respects aag l \<top> (set_original slot v)"
unfolding set_original_def
apply (unfold equiv_valid_def2)
apply (rule_tac Q="\<top>\<top>" in equiv_valid_rv_bind)
apply (rule gets_is_original_cap_revrv)
apply (rule modify_ev2)
apply (clarsimp simp: equiv_for_or or_comp_dist)
apply (safe)
apply (erule reads_equiv_is_original_cap_update)
apply (erule equiv_for_id_update)
apply (erule affects_equiv_is_original_cap_update)
apply (erule equiv_for_id_update)
apply wp
done
lemma set_cdt_reads_respects:
"reads_respects aag l \<top> (set_cdt c)"
unfolding set_cdt_def
apply (unfold equiv_valid_def2)
apply (rule get_bind_ev2)
apply (unfold fun_app_def, rule put_ev2)
apply (fastforce intro: reads_equiv_cdt_update affects_equiv_cdt_update equiv_for_refl)
done
lemma set_cdt_ev2:
"equiv_for (((aag_can_read aag) or (aag_can_affect aag l)) \<circ> fst) id c c'
\<Longrightarrow> equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l)
(=) \<top> \<top> (set_cdt c) (set_cdt c')"
unfolding set_cdt_def
apply (rule get_bind_ev2)
apply (unfold fun_app_def, rule put_ev2)
apply (fastforce simp: equiv_for_or or_comp_dist reads_equiv_cdt_update affects_equiv_cdt_update)
done
lemma set_cdt_list_ev2:
"equiv_for (((aag_can_read aag) or (aag_can_affect aag l)) \<circ> fst) id c c'
\<Longrightarrow> equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l)
(=) \<top> \<top> (set_cdt_list c) (set_cdt_list c')"
unfolding set_cdt_list_def
apply (rule get_bind_ev2)
apply (unfold fun_app_def, rule put_ev2)
apply (fastforce simp: equiv_for_or or_comp_dist reads_equiv_cdt_list_update affects_equiv_cdt_list_update)
done
lemma kheap_get_tcb_eq: "kheap s ref = kheap t ref \<Longrightarrow> get_tcb ref s = get_tcb ref t"
by (simp add: get_tcb_def)
lemma thread_get_rev:
"reads_equiv_valid_inv A aag (K (aag_can_read aag thread)) (thread_get f thread)"
unfolding thread_get_def fun_app_def
by (wp gets_the_ev) (fastforce intro: kheap_get_tcb_eq elim: reads_equivE equiv_forD)
lemma update_cdt_reads_respects:
"reads_respects aag l (K (\<forall>rv rv'.
equiv_for ((aag_can_read aag or aag_can_affect aag l) \<circ> fst) id rv rv' \<longrightarrow>
equiv_for ((aag_can_read aag or aag_can_affect aag l) \<circ> fst) f rv rv'))
(update_cdt f)"
unfolding update_cdt_def
apply (rule gen_asm_ev)
apply (unfold equiv_valid_def2)
apply (rule equiv_valid_rv_bind)
apply (rule equiv_valid_rv_guard_imp[OF gets_cdt_revrv])
apply (rule TrueI)
apply (rule set_cdt_ev2)
apply (simp add: equiv_for_comp[symmetric])
apply wp
done
lemma update_cdt_list_reads_respects:
"reads_respects aag l (K (\<forall>rv rv'.
equiv_for ((aag_can_read aag or aag_can_affect aag l) \<circ> fst) id rv rv' \<longrightarrow>
equiv_for ((aag_can_read aag or aag_can_affect aag l) \<circ> fst) f rv rv'))
(update_cdt_list f)"
unfolding update_cdt_list_def
apply (rule gen_asm_ev)
apply (unfold equiv_valid_def2)
apply (rule equiv_valid_rv_bind)
apply (rule equiv_valid_rv_guard_imp[OF gets_cdt_list_revrv])
apply (rule TrueI)
apply (rule set_cdt_list_ev2)
apply (simp add: equiv_for_comp[symmetric])
apply wp
done
lemma gen_asm_ev2':
assumes "Q \<Longrightarrow> Q' \<Longrightarrow> equiv_valid_2 I A B R P P' f f'"
shows "equiv_valid_2 I A B R (P and K Q) (P' and K Q') f f'"
using assms by (fastforce simp: equiv_valid_def2 equiv_valid_2_def)
lemmas gen_asm_ev2 = gen_asm_ev2'[where P=\<top> and P'=\<top>, simplified]
lemma set_untyped_cap_as_full_reads_respects:
"reads_respects aag l (K (aag_can_read aag (fst src_slot)))
(set_untyped_cap_as_full src_cap new_cap src_slot)"
unfolding set_untyped_cap_as_full_def
apply (wp set_cap_reads_respects)
apply auto
done
lemma gets_apply_wp[wp]:
"\<lbrace>\<lambda>s. P (f s x) s\<rbrace> gets_apply f x \<lbrace>P\<rbrace>"
by (wpsimp simp: gets_apply_def)
lemma cap_insert_reads_respects:
notes split_paired_All[simp del]
shows
"reads_respects aag l (K (aag_can_read aag (fst src_slot) \<and> aag_can_read aag (fst dest_slot)))
(cap_insert new_cap src_slot dest_slot)"
unfolding cap_insert_def
apply (rule gen_asm_ev)
apply (subst gets_apply)
apply (simp only: cap_insert_ext_extended.dxo_eq)
apply (simp only: cap_insert_ext_def)
apply (wp set_original_reads_respects update_cdt_reads_respects set_cap_reads_respects
gets_apply_ev update_cdt_list_reads_respects set_untyped_cap_as_full_reads_respects
get_cap_wp get_cap_rev
| simp split del: if_split
| clarsimp simp: equiv_for_def split: option.splits)+
by (fastforce simp: reads_equiv_def2 equiv_for_def
elim: states_equiv_forE_is_original_cap states_equiv_forE_cdt
dest: aag_can_read_self
split: option.splits)
lemma cap_move_reads_respects:
notes split_paired_All[simp del]
shows
"reads_respects aag l (K (is_subject aag (fst src_slot) \<and> is_subject aag (fst dest_slot)))
(cap_move new_cap src_slot dest_slot)"
unfolding cap_move_def
apply (subst gets_apply)
apply (simp add: bind_assoc[symmetric])
apply (fold update_cdt_def)
apply (simp add: bind_assoc cap_move_ext_def)
apply (rule gen_asm_ev)
apply (elim conjE)
apply (wp set_original_reads_respects gets_apply_ev update_cdt_reads_respects
set_cap_reads_respects update_cdt_list_reads_respects
| simp split del: if_split | fastforce simp: equiv_for_def split: option.splits)+
apply (intro impI conjI allI)
apply (fastforce simp: reads_equiv_def2 equiv_for_def
elim: states_equiv_forE_is_original_cap states_equiv_forE_cdt
dest: aag_can_read_self
split: option.splits)+
done
lemma get_idemp:
"do s1 \<leftarrow> get; s2 \<leftarrow> get; f s1 s2 od =
do s1 \<leftarrow> get; f s1 s1 od"
by (simp add: get_def bind_def)
lemma gets_apply2:
"gets f >>= (\<lambda> f. g (f x) (f y)) =
gets_apply f x >>= (\<lambda> x. gets_apply f y >>= (\<lambda> y. g x y))"
by (simp add: gets_def gets_apply_def get_idemp)
lemma cap_swap_reads_respects:
notes split_paired_All[simp del]
shows "reads_respects aag l (K (is_subject aag (fst slot1) \<and> is_subject aag (fst slot2)))
(cap_swap cap1 slot1 cap2 slot2)"
unfolding cap_swap_def
apply (subst gets_apply2)
apply (simp add: bind_assoc[symmetric])
apply (fold update_cdt_def)
apply (simp add: bind_assoc cap_swap_ext_def)
apply (rule gen_asm_ev)
apply (wp set_original_reads_respects update_cdt_reads_respects gets_apply_ev
set_cap_reads_respects update_cdt_list_reads_respects
| simp split del: if_split | fastforce simp: equiv_for_def split: option.splits)+
apply (intro impI conjI allI)
apply ((fastforce simp: reads_equiv_def2 equiv_for_def
elim: states_equiv_forE_is_original_cap states_equiv_forE_cdt
dest: aag_can_read_self
split: option.splits)+)[2]
apply (frule_tac x = slot1 in equiv_forD, elim conjE,drule aag_can_read_self,simp)
apply (frule_tac x = slot2 in equiv_forD, elim conjE)
apply (drule aag_can_read_self)+
apply clarsimp
apply clarsimp
apply (erule equiv_forE)
apply (fastforce intro: equiv_forI)
apply (fastforce simp: equiv_for_def dest: aag_can_read_self
elim: reads_equivE equiv_forE[where f="is_original_cap"] split: option.splits)+
done
lemma tcb_at_def2: "tcb_at ptr s = (\<exists>tcb. kheap s ptr = Some (TCB tcb))"
by (clarsimp simp: tcb_at_def get_tcb_def split: kernel_object.splits option.splits)
lemma set_cdt_globals_equiv:
"set_cdt c \<lbrace>globals_equiv s\<rbrace>"
unfolding set_cdt_def
by (wpsimp simp: globals_equiv_def idle_equiv_def)
lemma update_cdt_globals_equiv:
"update_cdt f \<lbrace>globals_equiv s\<rbrace>"
unfolding update_cdt_def
by (wp set_cdt_globals_equiv)
declare set_original_wp[wp del]
lemma set_original_globals_equiv:
"set_original slot v \<lbrace>globals_equiv s\<rbrace>"
unfolding set_original_def
by (wpsimp simp: globals_equiv_def idle_equiv_def)
lemma globals_equiv_exst_update[simp]:
"globals_equiv st (trans_state f s) =
globals_equiv st s"
by (simp add: globals_equiv_def idle_equiv_def)
lemma (in is_extended') globals_equiv: "I (globals_equiv st)" by (rule lift_inv,simp)
lemma domain_sep_inv_refl:
"domain_sep_inv irqs st s \<Longrightarrow> domain_sep_inv irqs s s"
by (fastforce simp: domain_sep_inv_def)
locale CNode_IF_1 =
fixes state_ext_t :: "'s :: state_ext itself"
and irq_at :: "nat \<Rightarrow> (irq \<Rightarrow> bool) \<Rightarrow> irq option"
assumes set_cap_globals_equiv:
"\<lbrace>globals_equiv s and valid_global_objs and valid_arch_state\<rbrace>
set_cap cap p
\<lbrace>\<lambda>_. globals_equiv s\<rbrace>"
and dmo_getActiveIRQ_wp:
"\<lbrace>\<lambda>s. P (irq_at (irq_state (machine_state s) + 1) (irq_masks (machine_state s)))
(s\<lparr>machine_state := machine_state s\<lparr>irq_state := irq_state (machine_state s) + 1\<rparr>\<rparr>)\<rbrace>
do_machine_op (getActiveIRQ in_kernel)
\<lbrace>\<lambda>rv s :: 's state. P rv s\<rbrace>"
and arch_globals_equiv_irq_state_update[simp]:
"arch_globals_equiv ct it kh kh' as as' ms (irq_state_update f ms') =
arch_globals_equiv ct it kh kh' as as' ms ms'"
"arch_globals_equiv ct it kh kh' as as' (irq_state_update f ms) ms' =
arch_globals_equiv ct it kh kh' as as' ms ms'"
begin
crunch set_untyped_cap_as_full
for globals_equiv[wp]: "globals_equiv st"
lemma cap_insert_globals_equiv:
"\<lbrace>globals_equiv s and valid_global_objs and valid_arch_state\<rbrace>
cap_insert new_cap src_slot dest_slot
\<lbrace>\<lambda>_. globals_equiv s\<rbrace>"
unfolding cap_insert_def fun_app_def
by (wpsimp wp: update_cdt_globals_equiv set_original_globals_equiv
set_cap_globals_equiv hoare_drop_imps dxo_wp_weak)
lemma cap_move_globals_equiv:
"\<lbrace>globals_equiv s and valid_global_objs and valid_arch_state\<rbrace>
cap_move new_cap src_slot dest_slot
\<lbrace>\<lambda>_. globals_equiv s\<rbrace>"
unfolding cap_move_def fun_app_def
by (wpsimp wp: set_original_globals_equiv set_cdt_globals_equiv set_cap_globals_equiv dxo_wp_weak)
lemma cap_swap_globals_equiv:
"\<lbrace>globals_equiv s and valid_global_objs and valid_arch_state\<rbrace>
cap_swap cap1 slot1 cap2 slot2
\<lbrace>\<lambda>_. globals_equiv s\<rbrace>"
unfolding cap_swap_def
by (wpsimp wp: set_original_globals_equiv set_cdt_globals_equiv set_cap_globals_equiv dxo_wp_weak)
definition is_irq_at :: "('z::state_ext) state \<Rightarrow> irq \<Rightarrow> nat \<Rightarrow> bool" where
"is_irq_at s \<equiv> \<lambda>irq pos. irq_at pos (irq_masks (machine_state s)) = Some irq"
text \<open>
We require that interrupts recur in order to ensure that no individual
big step ever diverges.
\<close>
definition irq_is_recurring :: "irq \<Rightarrow> ('z::state_ext) state \<Rightarrow> bool" where
"irq_is_recurring irq s \<equiv> \<forall>n. (\<exists>m. is_irq_at s irq (n+m))"
text \<open>
There is only one interrupt turned on, namely @{term irq}, and it is
a timer interrupt.
\<close>
definition only_timer_irq :: "irq \<Rightarrow> 'z::state_ext state \<Rightarrow> bool" where
"only_timer_irq irq s \<equiv> (\<forall>x. interrupt_states s x = IRQTimer \<longrightarrow> x = irq) \<and> irq_is_recurring irq s"
end
locale CNode_IF_2 = CNode_IF_1 state_ext_t
for state_ext_t :: "'s :: state_ext itself"
and f :: "('s state, 'a) nondet_monad" +
assumes is_irq_at_triv:
"(\<And>P. \<lbrace>(\<lambda>s. P (irq_masks (machine_state s))) and Q\<rbrace>
f
\<lbrace>\<lambda>rv s. P (irq_masks (machine_state s))\<rbrace>)
\<Longrightarrow> \<lbrace>(\<lambda>s. P (is_irq_at s)) and Q\<rbrace>
f
\<lbrace>\<lambda>rv s. P (is_irq_at s)\<rbrace>"
and is_irq_at_not_masked:
"is_irq_at (s :: det_state) irq pos \<Longrightarrow> \<not> irq_masks (machine_state s) irq"
begin
lemma irq_is_recurring_triv:
assumes a: "\<And>P. \<lbrace>(\<lambda>s. P (irq_masks (machine_state s))) and Q\<rbrace>
(f :: ('s state, 'a) nondet_monad)
\<lbrace>\<lambda>rv s. P (irq_masks (machine_state s))\<rbrace>"
shows "\<lbrace>irq_is_recurring irq and Q\<rbrace> f \<lbrace>\<lambda>_. irq_is_recurring irq\<rbrace>"
apply (clarsimp simp: irq_is_recurring_def valid_def)
apply (rule use_valid[OF _ is_irq_at_triv[OF a]])
apply assumption
apply simp
done
lemma domain_sep_inv_to_interrupt_states_pres:
assumes a: "\<And>st. \<lbrace>domain_sep_inv False (st :: 's state) and P\<rbrace> f \<lbrace>\<lambda>_. domain_sep_inv False st\<rbrace>"
shows "\<lbrace>(\<lambda>s. Q (interrupt_states s)) and P and domain_sep_inv False st\<rbrace>
f
\<lbrace>\<lambda>_ s. Q (interrupt_states s)\<rbrace>"
apply (clarsimp simp: valid_def)
apply (erule use_valid)
apply (rule hoare_strengthen_post)
apply (rule_tac st3=s in a)
apply (fastforce simp: domain_sep_inv_def)
apply (simp add: domain_sep_inv_refl)
done
lemma only_timer_irq_pres:
assumes a: "\<And>P. \<lbrace>(\<lambda>s. P (irq_masks (machine_state s))) and Q\<rbrace>
f
\<lbrace>\<lambda>rv s. P (irq_masks (machine_state s))\<rbrace>"
assumes b:
"\<And>st :: 's state. \<lbrace>domain_sep_inv False st and P\<rbrace> f \<lbrace>\<lambda>_. domain_sep_inv False st\<rbrace>"
shows
"\<lbrace>only_timer_irq irq and Q and P and (\<lambda>s. domain_sep_inv False (st :: 's state) s)\<rbrace>
f
\<lbrace>\<lambda>_. only_timer_irq irq\<rbrace>"
apply (clarsimp simp: only_timer_irq_def valid_def)
apply (rule conjI)
apply (clarsimp)
apply (drule spec)
apply (erule mp)
apply (erule contrapos_pp, erule use_valid, rule domain_sep_inv_to_interrupt_states_pres, rule b, fastforce)
apply (erule use_valid[OF _ irq_is_recurring_triv[OF a]])
by simp
definition only_timer_irq_inv :: "irq \<Rightarrow> 'z :: state_ext state \<Rightarrow> 'z state \<Rightarrow> bool" where
"only_timer_irq_inv irq st \<equiv> domain_sep_inv False st and only_timer_irq irq"
lemma only_timer_irq_inv_pres:
assumes a:
"\<And>P. \<lbrace>(\<lambda>s. P (irq_masks (machine_state s))) and Q\<rbrace>
f
\<lbrace>\<lambda>rv s. P (irq_masks (machine_state s))\<rbrace>"
assumes b: "\<And>st :: 's state. \<lbrace>domain_sep_inv False st and P\<rbrace> f \<lbrace>\<lambda>_. domain_sep_inv False st\<rbrace>"
shows "\<lbrace>only_timer_irq_inv irq (st :: 's state) and Q and P\<rbrace> f \<lbrace>\<lambda>_. only_timer_irq_inv irq st\<rbrace>"
apply (clarsimp simp: only_timer_irq_inv_def valid_def)
apply (rule conjI)
apply (erule use_valid[OF _ b], simp)
apply (erule use_valid[OF _ only_timer_irq_pres[OF a b]])
apply simp
done
lemma only_timer_irq_inv_domain_sep_inv[intro]:
"only_timer_irq_inv irq st s \<Longrightarrow> domain_sep_inv False st s"
by (simp add: only_timer_irq_inv_def)
lemma irq_is_recurring_not_masked:
"irq_is_recurring irq (s :: det_state) \<Longrightarrow> \<not> irq_masks (machine_state s) irq"
apply (clarsimp simp: irq_is_recurring_def)
apply (blast dest: is_irq_at_not_masked)
done
lemma only_timer_irq_inv_determines_irq_masks:
"\<lbrakk>invs (s :: det_state); only_timer_irq_inv irq st s\<rbrakk> \<Longrightarrow>
\<not> irq_masks (machine_state s) irq \<and>
(\<forall>x. x \<noteq> irq \<longrightarrow> irq_masks (machine_state s) x)"
apply (rule conjI)
apply (clarsimp simp: only_timer_irq_inv_def only_timer_irq_def)
apply (blast dest: irq_is_recurring_not_masked)
apply (clarsimp simp: only_timer_irq_inv_def domain_sep_inv_def only_timer_irq_def)
apply (case_tac "interrupt_states s x")
apply (fastforce simp: invs_def valid_state_def valid_irq_states_def valid_irq_masks_def)
apply fastforce+
done
lemma dmo_getActiveIRQ_globals_equiv:
"\<lbrace>globals_equiv st\<rbrace> do_machine_op (getActiveIRQ in_kernel) \<lbrace>\<lambda>_. globals_equiv st\<rbrace>"
apply (wp dmo_getActiveIRQ_wp)
apply (auto simp: globals_equiv_def idle_equiv_def)
done
crunch reset_work_units, work_units_limit_reached, update_work_units
for only_timer_irq_inv[wp]: "only_timer_irq_inv irq st"
(simp: only_timer_irq_inv_def only_timer_irq_def irq_is_recurring_def is_irq_at_def)
end
lemma gets_irq_masks_equiv_valid:
"equiv_valid_inv I A (\<lambda>s. \<not> (irq_masks s) irq \<and> (\<forall>x. x \<noteq> irq \<longrightarrow> (irq_masks s) x)) (gets irq_masks)"
by (fastforce simp: equiv_valid_def2 equiv_valid_2_def in_monad)
lemma irq_state_increment_reads_respects_memory:
"equiv_valid_inv (equiv_machine_state P and equiv_irq_state)
(equiv_for (\<lambda>x. aag_can_affect_label aag l \<and>
pasObjectAbs aag x \<in> subjectReads (pasPolicy aag) l)
underlying_memory)
\<top> (modify (\<lambda>s. s\<lparr>irq_state := Suc (irq_state s)\<rparr>))"
apply (simp add: equiv_valid_def2)
apply (rule modify_ev2)
apply (fastforce intro: equiv_forI elim: equiv_forE)
done
lemma irq_state_increment_reads_respects_device:
"equiv_valid_inv (equiv_machine_state P and equiv_irq_state)
(equiv_for (\<lambda>x. aag_can_affect_label aag l \<and>
pasObjectAbs aag x \<in> subjectReads (pasPolicy aag) l)
device_state)
\<top> (modify (\<lambda>s. s\<lparr>irq_state := Suc (irq_state s)\<rparr>))"
apply (simp add: equiv_valid_def2)
apply (rule modify_ev2)
apply (fastforce intro: equiv_forI elim: equiv_forE)
done
lemma use_equiv_valid_inv:
"\<lbrakk> x \<in> fst (f st); y \<in> fst (f s); g s; g st; I s st; P s st; equiv_valid_inv I P g f \<rbrakk>
\<Longrightarrow> fst x = fst y \<and> P (snd y) (snd x) \<and> I (snd y) (snd x)"
apply (clarsimp simp add: equiv_valid_def spec_equiv_valid_def equiv_valid_2_def)
apply (drule spec)+
apply (erule impE)
apply fastforce
apply (drule(1) bspec | clarsimp)+
done
lemma equiv_valid_inv_conj_lift:
assumes P: "equiv_valid_inv I (\<lambda>s s'. P s s') g f"
and P': "equiv_valid_inv I (\<lambda>s s'. P' s s') g f"
shows "equiv_valid_inv I (\<lambda>s s'. P s s' \<and> P' s s') g f"
apply (clarsimp simp add: equiv_valid_def spec_equiv_valid_def equiv_valid_2_def)
apply (frule_tac st = t and s = st in use_equiv_valid_inv[OF _ _ _ _ _ _ P])
apply fastforce+
apply (frule_tac st = t and s = st in use_equiv_valid_inv[OF _ _ _ _ _ _ P'])
apply fastforce+
done
lemma reset_work_units_reads_respects[wp]:
"reads_respects aag l \<top> reset_work_units"
apply (simp add: reset_work_units_def equiv_valid_def2)
apply (rule modify_ev2)
apply (force intro: reads_equiv_work_units_completed_update affects_equiv_work_units_completed_update)
done
lemma update_work_units_reads_respects[wp]:
"reads_respects aag l \<top> update_work_units"
apply (simp add: update_work_units_def equiv_valid_def2)
apply (rule modify_ev2)
apply (force intro: reads_equiv_work_units_completed_update' affects_equiv_work_units_completed_update')
done
lemma work_units_limit_reached_reads_respects[wp]:
"reads_respects aag l \<top> work_units_limit_reached"
apply (simp add: work_units_limit_reached_def, wp)
apply force
done
crunch work_units_limit_reached
for invs[wp]: invs
lemma preemption_point_def2:
"(preemption_point :: (unit,det_ext) p_monad) =
doE liftE update_work_units;
rv \<leftarrow> liftE work_units_limit_reached;
if rv then doE liftE reset_work_units;
liftE (do_machine_op (getActiveIRQ True)) >>=E
case_option (returnOk ()) (K (throwError $ ()))
odE
else returnOk()
odE"
apply (rule ext)
apply (simp add: preemption_point_def OR_choiceE_def wrap_ext_bool_det_ext_ext_def
ef_mk_ef work_units_limit_reached_def select_f_def empty_fail_cond)
apply (clarsimp simp: work_units_limit_reached_def gets_def liftE_def select_f_def get_def
lift_def return_def bind_def bindE_def split_def image_def
split: option.splits sum.splits)
done
lemma all_children_descendants_equal:
"\<lbrakk> equiv_for P id s t; all_children P s; all_children P t; P slot \<rbrakk>
\<Longrightarrow> descendants_of slot s = descendants_of slot t"
apply (clarsimp | rule equalityI)+
apply (frule_tac p="(a, b)" and q="slot" and m=s in all_children_descendants_of)
apply (simp)+
apply (simp add: descendants_of_def cdt_parent_rel_def is_cdt_parent_def)
apply (rule_tac r'="{(p, c). s c = Some p}" and Q="P" in trancl_subset_equivalence)
apply (clarsimp)+
apply (frule_tac p="(aa, ba)" and q="slot" in all_children_descendants_of)
apply (fastforce simp: descendants_of_def cdt_parent_rel_def is_cdt_parent_def)+
apply (fastforce simp: equiv_for_def)
apply (clarsimp)
apply (frule_tac p="(a, b)" and q="slot" and m=t in all_children_descendants_of)
apply (simp)+
apply (simp add: descendants_of_def cdt_parent_rel_def is_cdt_parent_def)
apply (rule_tac r'="{(p, c). t c = Some p}" and Q="P" in trancl_subset_equivalence)
apply (clarsimp)+
apply (frule_tac p="(aa, ba)" and q="slot" and m=t in all_children_descendants_of)
apply (fastforce simp: equiv_for_def descendants_of_def cdt_parent_rel_def is_cdt_parent_def)+
done
lemma cca_can_read:
"\<lbrakk> valid_mdb s; valid_objs s; cdt_change_allowed' aag slot s; pas_refined aag s \<rbrakk>
\<Longrightarrow> aag_can_read aag (fst slot)"
apply (frule(3) cdt_change_allowed_delete_derived)
by (rule read_delder_thread_read_thread_rev[OF reads_lrefl])
lemma all_children_subjectReads:
"pas_refined aag s \<Longrightarrow> all_children (aag_can_read aag \<circ> fst) (cdt s)"
apply (rule all_childrenI)
apply simp
apply (erule read_delder_thread_read_thread_rev)
by (rule aag_cdt_link_DeleteDerived)
lemma descendants_of_eq:
"\<lbrakk> reads_equiv aag s t; affects_equiv aag l s t;
pas_refined aag s; pas_refined aag t; is_subject aag (fst slot) \<rbrakk>
\<Longrightarrow> descendants_of slot (cdt s) = descendants_of slot (cdt t)"
apply (rule all_children_descendants_equal[OF _ all_children_subjectReads all_children_subjectReads])
apply (elim reads_equivE)
apply (solves\<open>simp add: equiv_for_apply\<close>)
by force+
lemma gets_descendants_of_revrv:
"reads_equiv_valid_rv_inv (affects_equiv aag l) aag (=)
(pas_refined aag and K (is_subject aag (fst slot)))
(gets (descendants_of slot \<circ> cdt))"
apply (rule gets_evrv'')
apply clarsimp
by (rule descendants_of_eq)
lemma silc_dom_equiv_trans[elim]:
"\<lbrakk> silc_dom_equiv aag s t; silc_dom_equiv aag t u \<rbrakk>
\<Longrightarrow> silc_dom_equiv aag s u"
by (auto simp: silc_dom_equiv_def elim: equiv_for_trans)
lemma silc_dom_equiv_sym[elim]:
"silc_dom_equiv aag s t \<Longrightarrow> silc_dom_equiv aag t s"
by (auto simp: silc_dom_equiv_def elim: equiv_for_sym)
lemma reads_respects_f:
"\<lbrakk> reads_respects aag l P f; \<lbrace>silc_inv aag st and Q\<rbrace> f \<lbrace>\<lambda>_. silc_inv aag st\<rbrace> \<rbrakk>
\<Longrightarrow> reads_respects_f aag l (silc_inv aag st and P and Q) f"
apply (clarsimp simp: equiv_valid_def2 equiv_valid_2_def reads_equiv_f_def)
apply (rule conjI, fastforce)
apply (rule conjI, fastforce)
apply (subst conj_commute, rule conjI, fastforce)
apply (rule silc_dom_equiv_trans)
apply (rule silc_dom_equiv_sym)
apply (rule silc_inv_silc_dom_equiv)
apply (erule (1) use_valid, simp)
apply (rule silc_inv_silc_dom_equiv)
apply (erule (1) use_valid, simp)
done
locale CNode_IF_3 = CNode_IF_2 +
fixes aag :: "'a subject_label PAS"
assumes dmo_getActiveIRQ_reads_respects:
"reads_respects aag l (invs and only_timer_irq_inv irq st) (do_machine_op (getActiveIRQ in_kernel))"
begin
lemma dmo_getActiveIRQ_reads_respects_g :
"reads_respects_g aag l (invs and only_timer_irq_inv irq st) (do_machine_op (getActiveIRQ in_kernel))"
apply (rule equiv_valid_guard_imp[OF reads_respects_g])
apply (rule dmo_getActiveIRQ_reads_respects)
apply (rule doesnt_touch_globalsI)
apply (wp dmo_getActiveIRQ_globals_equiv | blast)+
done
lemma preemption_point_reads_respects:
"reads_respects aag l (invs and only_timer_irq_inv irq st) preemption_point"
apply (simp add: preemption_point_def2)
apply (wp | wpc | simp add: comp_def)+
apply ((wp dmo_getActiveIRQ_reads_respects hoare_TrueI | simp
| wp (once) hoare_drop_imps)+)[8]
apply wp
apply force
done
lemma preemption_point_reads_respects_f:
"reads_respects_f aag l (invs and only_timer_irq_inv irq st' and silc_inv aag st) preemption_point"
apply (rule equiv_valid_guard_imp)
apply (rule reads_respects_f)
apply (rule preemption_point_reads_respects)
apply (wp, force+)
done
end
abbreviation
reads_spec_equiv_valid_f ::
"det_state \<Rightarrow> (det_state \<Rightarrow> det_state \<Rightarrow> bool) \<Rightarrow> (det_state \<Rightarrow> det_state \<Rightarrow> bool) \<Rightarrow>
'a subject_label PAS \<Rightarrow> (det_state \<Rightarrow> bool) \<Rightarrow> (det_state, 'b) nondet_monad \<Rightarrow> bool" where
"reads_spec_equiv_valid_f s A B aag P f \<equiv> spec_equiv_valid s (reads_equiv_f aag) A B P f"
abbreviation reads_spec_equiv_valid_f_inv
where
"reads_spec_equiv_valid_f_inv s A aag P f \<equiv> reads_spec_equiv_valid_f s A A aag P f"
abbreviation
spec_reads_respects_f :: "det_state \<Rightarrow> 'a subject_label PAS \<Rightarrow> 'a subject_label \<Rightarrow>
(det_state \<Rightarrow> bool) \<Rightarrow> (det_state,'b) nondet_monad \<Rightarrow> bool" where
"spec_reads_respects_f s aag l P f \<equiv> reads_spec_equiv_valid_f_inv s (affects_equiv aag l) aag P f"
definition reads_equiv_f_g where
"reads_equiv_f_g aag s s' \<equiv> reads_equiv aag s s' \<and> globals_equiv s s' \<and> silc_dom_equiv aag s s'"
abbreviation reads_respects_f_g :: "'a subject_label PAS \<Rightarrow> 'a subject_label \<Rightarrow>
(det_state \<Rightarrow> bool) \<Rightarrow> (det_state,'b) nondet_monad \<Rightarrow> bool" where
"reads_respects_f_g aag l P f \<equiv>
equiv_valid_inv (reads_equiv_f_g aag) (affects_equiv aag l) P f"
lemma reads_equiv_f_g_conj:
"reads_equiv_f_g aag s s' \<equiv> reads_equiv_f aag s s' \<and> reads_equiv_g aag s s'"
by (simp add: reads_equiv_f_g_def reads_equiv_f_def reads_equiv_g_def conj_comms)
lemma reads_respects_f_g:
"\<lbrakk> reads_respects_f aag l P f; doesnt_touch_globals Q f \<rbrakk>
\<Longrightarrow> reads_respects_f_g aag l (P and Q) f"
apply (clarsimp simp: equiv_valid_def2 equiv_valid_2_def)
apply (subst (asm) reads_equiv_f_g_conj, erule conjE)
apply (subst reads_equiv_f_g_conj)
apply (drule reads_equiv_gD)
apply clarsimp
apply (subgoal_tac "reads_equiv_g aag b ba", blast)
apply (subgoal_tac "globals_equiv b ba", fastforce intro: reads_equiv_gI simp: reads_equiv_f_def)
apply (rule globals_equiv_trans)
apply (rule globals_equiv_sym)
apply (fastforce intro: globals_equivI)
apply (rule globals_equiv_trans)
apply (assumption)
apply (fastforce intro: globals_equivI)
done
lemma reads_equiv_valid_rv_inv_f:
assumes a: "reads_equiv_valid_rv_inv A aag R P f"
assumes b: "\<And>P. \<lbrace>P\<rbrace> f \<lbrace>\<lambda>_. P\<rbrace>"
shows "equiv_valid_rv_inv (reads_equiv_f aag) A R P f"
apply (clarsimp simp: equiv_valid_2_def reads_equiv_f_def)
apply (insert a, clarsimp simp: equiv_valid_2_def)
apply (drule_tac x=s in spec, drule_tac x=t in spec, clarsimp)
apply (drule (1) bspec, clarsimp)
apply (drule (1) bspec, clarsimp)
apply (drule state_unchanged[OF b])+
by simp
lemma set_cap_silc_inv':
"\<lbrace>silc_inv aag st and (\<lambda>s. \<not> cap_points_to_label aag cap (pasObjectAbs aag (fst slot))
\<longrightarrow> (\<exists>lslot. lslot \<in> slots_holding_overlapping_caps cap s \<and>
pasObjectAbs aag (fst lslot) = SilcLabel))
and K (pasObjectAbs aag (fst slot) \<noteq> SilcLabel)\<rbrace>
set_cap cap slot
\<lbrace>\<lambda>_. silc_inv aag st\<rbrace>"
apply (rule hoare_pre)
apply (rule set_cap_silc_inv)
by blast
lemma set_cap_reads_respects_f:
"reads_respects_f aag l
(silc_inv aag st and (\<lambda>s. \<not> cap_points_to_label aag cap (pasObjectAbs aag (fst slot))
\<longrightarrow> (\<exists>lslot. lslot \<in> slots_holding_overlapping_caps cap s \<and>
pasObjectAbs aag (fst lslot) = SilcLabel))
and K (is_subject aag (fst slot))) (set_cap cap slot)"
apply (rule equiv_valid_guard_imp)
apply (rule reads_respects_f[OF set_cap_reads_respects])
apply (wp set_cap_silc_inv')
apply (auto simp: silc_inv_def)
done
lemma select_ext_ev:
"(\<And>s t. I s t \<Longrightarrow> A s t \<Longrightarrow> a s \<in> S \<Longrightarrow> a t \<in> S \<Longrightarrow> a s = a t)
\<Longrightarrow> equiv_valid_inv I A (\<top> :: det_state \<Rightarrow> bool) (select_ext a S)"
apply (clarsimp simp: select_ext_def gets_def get_def assert_def return_def bind_def)
apply (simp add: equiv_valid_def2 equiv_valid_2_def return_def fail_def)
done
end