~james/split

ref: 36fd34c5221ae47ee29e89ecfbab8662ab4fd6f5 split/Execution.thy -rw-r--r-- 5.7 KiB
36fd34c5 — james test(pager): check recycling preserves isolation after remapping 2 months ago
                                                                                
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
theory Execution
  imports Isolation
begin

datatype action = Read nat nat | Write nat nat nat

fun valid :: "nat \<Rightarrow> nat \<Rightarrow> action \<Rightarrow> bool" where
  "valid slots bytes (Read k offset) = (k < slots \<and> offset < bytes)"
| "valid slots bytes (Write k offset byte) = (k < slots \<and> offset < bytes \<and> byte < 256)"

fun advance :: "pager \<Rightarrow> action \<Rightarrow> pager" where
  "advance s (Read k offset) = s"
| "advance s (Write k offset byte) = store s k offset byte"

fun reference :: "memory \<Rightarrow> action \<Rightarrow> memory" where
  "reference m (Read k offset) = m"
| "reference m (Write k offset byte) = reference_write m k offset byte"

fun observe :: "pager \<Rightarrow> action \<Rightarrow> nat" where
  "observe s (Read k offset) = view s k offset"
| "observe s (Write k offset byte) = byte"

fun reference_observe :: "memory \<Rightarrow> action \<Rightarrow> nat" where
  "reference_observe m (Read k offset) = m k offset"
| "reference_observe m (Write k offset byte) = byte"

fun execute :: "pager \<Rightarrow> action list \<Rightarrow> pager" where
  "execute s [] = s"
| "execute s (a # actions) = execute (advance s a) actions"

fun reference_execute :: "memory \<Rightarrow> action list \<Rightarrow> memory" where
  "reference_execute m [] = m"
| "reference_execute m (a # actions) = reference_execute (reference m a) actions"

fun observations :: "pager \<Rightarrow> action list \<Rightarrow> nat list" where
  "observations s [] = []"
| "observations s (a # actions) = observe s a # observations (advance s a) actions"

fun reference_observations :: "memory \<Rightarrow> action list \<Rightarrow> nat list" where
  "reference_observations m [] = []"
| "reference_observations m (a # actions) =
    reference_observe m a # reference_observations (reference m a) actions"

lemma advance_invariant:
  "invariant n s \<Longrightarrow> invariant n (advance s a)"
  by (cases a; simp add: write_invariant)

lemma advance_simulation:
  "invariant n s \<Longrightarrow> represents n s m \<Longrightarrow> valid n bytes a \<Longrightarrow>
   represents n (advance s a) (reference m a)"
  by (cases a; auto intro: simulation)

lemma observe_simulation:
  "represents n s m \<Longrightarrow> valid n bytes a \<Longrightarrow>
   observe s a = reference_observe m a"
  by (cases a; auto simp: represents_def)

theorem execute_invariant:
  "invariant n s \<Longrightarrow> invariant n (execute s actions)"
  by (induction actions arbitrary: s) (auto intro: advance_invariant)

theorem execute_refinement:
  assumes "invariant n s" "represents n s m" "list_all (valid n bytes) actions"
  shows "represents n (execute s actions) (reference_execute m actions)"
  using assms
  by (induction actions arbitrary: s m)
     (auto intro: advance_invariant advance_simulation)

theorem observable_equivalence:
  assumes "invariant n s" "represents n s m" "list_all (valid n bytes) actions"
  shows "observations s actions = reference_observations m actions"
  using assms
  by (induction actions arbitrary: s m)
     (auto intro: advance_invariant advance_simulation observe_simulation)

definition admitted :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> pager \<Rightarrow> action \<Rightarrow> bool" where
  "admitted slots bytes capacity s a \<longleftrightarrow> valid slots bytes a \<and>
    (case a of Read k offset \<Rightarrow> True
     | Write k offset byte \<Rightarrow> writable s k \<or> frontier s < capacity)"

definition checked :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> pager \<Rightarrow> action \<Rightarrow> pager option" where
  "checked slots bytes capacity s a =
    (if admitted slots bytes capacity s a then Some (advance s a) else None)"

lemma checked_failure:
  "\<not> admitted slots bytes capacity s a \<Longrightarrow> checked slots bytes capacity s a = None"
  by (simp add: checked_def)

lemma checked_success:
  "checked slots bytes capacity s a = Some t \<Longrightarrow> t = advance s a"
  by (auto simp: checked_def split: if_splits)

theorem checked_invariant:
  "invariant slots s \<Longrightarrow> checked slots bytes capacity s a = Some t \<Longrightarrow>
   invariant slots t"
  using checked_success advance_invariant by blast

theorem checked_capacity:
  "frontier s \<le> capacity \<Longrightarrow> checked slots bytes capacity s a = Some t \<Longrightarrow>
   frontier t \<le> capacity"
  by (cases a; auto simp: checked_def admitted_def prepare_frontier split: if_splits)

theorem checked_simulation:
  "invariant slots s \<Longrightarrow> represents slots s m \<Longrightarrow>
   checked slots bytes capacity s a = Some t \<Longrightarrow>
   represents slots t (reference m a)"
  by (auto simp: checked_def admitted_def split: if_splits intro: advance_simulation)

lemma invalid_slot_rejected:
  "slots \<le> k \<Longrightarrow> checked slots bytes capacity s (Write k offset byte) = None"
  by (simp add: checked_def admitted_def)

lemma invalid_offset_rejected:
  "bytes \<le> offset \<Longrightarrow> checked slots bytes capacity s (Write k offset byte) = None"
  by (simp add: checked_def admitted_def)

lemma invalid_byte_rejected:
  "256 \<le> byte \<Longrightarrow> checked slots bytes capacity s (Write k offset byte) = None"
  by (simp add: checked_def admitted_def)

lemma exhausted_readonly_rejected:
  "\<not> writable s k \<Longrightarrow> capacity \<le> frontier s \<Longrightarrow>
   checked slots bytes capacity s (Write k offset byte) = None"
  by (simp add: checked_def admitted_def)

lemma exhausted_writable_allowed:
  "writable s k \<Longrightarrow> valid slots bytes (Write k offset byte) \<Longrightarrow>
   checked slots bytes capacity s (Write k offset byte) = Some (store s k offset byte)"
  by (simp add: checked_def admitted_def)

end