Skip to content

Commit 8625707

Browse files
committed
Prove lemma_va_level_to_nid_inc
1 parent 5160ce0 commit 8625707

2 files changed

Lines changed: 117 additions & 53 deletions

File tree

lock-protocol/src/exec/rw/common.rs

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,123 @@ pub proof fn lemma_va_level_to_nid_inc(va: Vaddr, level: PagingLevel, nid: NodeI
135135
ensures
136136
NodeHelper::get_child(nid, idx) == va_level_to_nid(va, level),
137137
{
138-
admit(); // TODO
138+
// Establish the relationship between traces at consecutive levels
139+
let trace_level_plus_1 = va_level_to_trace(va, (level + 1) as PagingLevel);
140+
let trace_level = va_level_to_trace(va, level);
141+
142+
// Show that trace_level = trace_level_plus_1.push(idx)
143+
assert(trace_level == trace_level_plus_1.push(idx)) by {
144+
// By definition: va_level_to_trace(va, level) = va_level_to_trace_rec(va >> 12, level)
145+
// And: va_level_to_trace_rec(va >> 12, level) = va_level_to_trace_rec(va >> 12, level + 1).push(((va >> 12 >> (level * 9)) & mask) as nat)
146+
// We need to show that ((va >> 12 >> (level * 9)) & mask) as nat == idx
147+
// Since idx = va_level_to_offset(va, level + 1) = ((va >> (12 + level * 9)) & mask) as nat
148+
// And (va >> 12 >> (level * 9)) = (va >> (12 + level * 9)) by bit shift properties
149+
// reveal(va_level_to_trace_rec);
150+
assert(va_level_to_trace_rec(va >> 12, level) == va_level_to_trace_rec(
151+
va >> 12,
152+
(level + 1) as PagingLevel,
153+
).push(((va >> 12 >> (level * 9)) & low_bits_mask(9) as usize) as nat));
154+
155+
// Show the bit extraction equivalence
156+
let offset = (va >> 12 >> (level * 9)) & low_bits_mask(9) as usize;
157+
assert(offset as nat == idx) by {
158+
// va_level_to_offset(va, level + 1) = ((va >> (12 + ((level + 1) - 1) * 9)) & mask) as nat
159+
// = ((va >> (12 + level * 9)) & mask) as nat
160+
// We need to show: (va >> 12 >> (level * 9)) & mask == (va >> (12 + level * 9)) & mask
161+
// This follows from bit shift associativity: a >> b >> c == a >> (b + c)
162+
assert(low_bits_mask(9) == 511) by {
163+
lemma_low_bits_mask_values();
164+
};
165+
assert((va >> 12 >> (level * 9)) == (va >> (12 + level * 9))) by (bit_vector);
166+
assert(((va >> 12 >> (level * 9)) & 511 as usize) == ((va >> (12 + level * 9))
167+
& 511 as usize)) by (bit_vector);
168+
}
169+
};
170+
171+
// Now use the fact that nid = trace_to_nid(trace_level_plus_1)
172+
// and get_child(nid, idx) = trace_to_nid(nid_to_trace(nid).push(idx))
173+
assert(NodeHelper::nid_to_trace(nid) == trace_level_plus_1) by {
174+
// First establish that trace_level_plus_1 is a valid trace
175+
assert(NodeHelper::valid_trace(trace_level_plus_1)) by {
176+
// trace_level_plus_1 = va_level_to_trace(va, level + 1)
177+
// Use the lemma that directly proves va_level_to_trace produces valid traces
178+
lemma_va_level_to_trace_valid(va, (level + 1) as PagingLevel);
179+
};
180+
181+
// Since nid = trace_to_nid(trace_level_plus_1) and trace_to_nid is bijective
182+
NodeHelper::lemma_nid_to_trace_sound(nid);
183+
NodeHelper::lemma_trace_to_nid_sound(trace_level_plus_1);
184+
// From the precondition: nid == va_level_to_nid(va, level + 1)
185+
// And va_level_to_nid(va, level + 1) == trace_to_nid(trace_level_plus_1)
186+
// So nid == trace_to_nid(trace_level_plus_1)
187+
// Since trace_to_nid is bijective, nid_to_trace(nid) == trace_level_plus_1
188+
assert(nid == NodeHelper::trace_to_nid(trace_level_plus_1));
189+
assert(NodeHelper::trace_to_nid(NodeHelper::nid_to_trace(nid)) == nid);
190+
assert(NodeHelper::trace_to_nid(NodeHelper::nid_to_trace(nid)) == NodeHelper::trace_to_nid(
191+
trace_level_plus_1,
192+
));
193+
NodeHelper::lemma_trace_to_nid_bijective();
194+
};
195+
196+
// Therefore get_child(nid, idx) = trace_to_nid(trace_level_plus_1.push(idx)) = trace_to_nid(trace_level)
197+
assert(NodeHelper::get_child(nid, idx) == NodeHelper::trace_to_nid(
198+
trace_level_plus_1.push(idx),
199+
));
200+
assert(trace_level_plus_1.push(idx) == trace_level);
201+
assert(NodeHelper::get_child(nid, idx) == NodeHelper::trace_to_nid(trace_level));
202+
assert(NodeHelper::trace_to_nid(trace_level) == va_level_to_nid(va, level));
203+
}
204+
205+
pub proof fn lemma_va_level_to_trace_rec_len(va: Vaddr, level: PagingLevel)
206+
requires
207+
1 <= level <= 4,
208+
ensures
209+
va_level_to_trace_rec(va, level).len() == 4 - level,
210+
decreases 4 - level,
211+
{
212+
if level < 4 {
213+
lemma_va_level_to_trace_rec_len(va, (level + 1) as PagingLevel);
214+
}
215+
}
216+
217+
pub proof fn lemma_va_level_to_trace_valid(va: Vaddr, level: PagingLevel)
218+
requires
219+
1 <= level <= 4,
220+
ensures
221+
NodeHelper::valid_trace(va_level_to_trace(va, level)),
222+
{
223+
lemma_va_level_to_trace_rec_valid(va >> 12, level);
224+
}
225+
226+
pub proof fn lemma_va_level_to_trace_rec_valid(va: Vaddr, level: PagingLevel)
227+
requires
228+
1 <= level <= 4,
229+
ensures
230+
NodeHelper::valid_trace(va_level_to_trace_rec(va, level)),
231+
decreases 4 - level,
232+
{
233+
if level < 4 {
234+
lemma_va_level_to_trace_rec_valid(va, (level + 1) as PagingLevel);
235+
let offset = (va >> (level * 9)) & low_bits_mask(9) as usize;
236+
assert(offset < 512) by {
237+
assert(low_bits_mask(9) == 511) by {
238+
lemma_low_bits_mask_values();
239+
};
240+
assert((va >> (level * 9)) & 511 <= 511) by (bit_vector);
241+
}
242+
// By inductive hypothesis, the recursive trace is valid
243+
assert(NodeHelper::valid_trace(va_level_to_trace_rec(va, (level + 1) as PagingLevel)));
244+
// Therefore its length is < 4
245+
assert(va_level_to_trace_rec(va, (level + 1) as PagingLevel).len() < 4);
246+
// Since we add exactly one element, the new length is still < 4
247+
assert(va_level_to_trace_rec(va, level).len() == va_level_to_trace_rec(
248+
va,
249+
(level + 1) as PagingLevel,
250+
).len() + 1);
251+
assert(va_level_to_trace_rec(va, (level + 1) as PagingLevel).len() + 1 <= 3) by {
252+
lemma_va_level_to_trace_rec_len(va, (level + 1) as PagingLevel);
253+
};
254+
}
139255
}
140256

141257
} // verus!

lock-protocol/src/exec/rw/cursor.rs

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -198,58 +198,6 @@ pub open spec fn va_range_get_tree_path(va: Range<Vaddr>) -> Seq<NodeId>
198198
NodeHelper::trace_to_tree_path(trace)
199199
}
200200

201-
pub proof fn lemma_va_level_to_trace_rec_len(va: Vaddr, level: PagingLevel)
202-
requires
203-
1 <= level <= 4,
204-
ensures
205-
va_level_to_trace_rec(va, level).len() == 4 - level,
206-
decreases 4 - level,
207-
{
208-
if level < 4 {
209-
lemma_va_level_to_trace_rec_len(va, (level + 1) as PagingLevel);
210-
}
211-
}
212-
213-
pub proof fn lemma_va_level_to_trace_rec_valid(va: Vaddr, level: PagingLevel)
214-
requires
215-
1 <= level <= 4,
216-
ensures
217-
NodeHelper::valid_trace(va_level_to_trace_rec(va, level)),
218-
decreases 4 - level,
219-
{
220-
if level < 4 {
221-
lemma_va_level_to_trace_rec_valid(va, (level + 1) as PagingLevel);
222-
let offset = (va >> (level * 9)) & low_bits_mask(9) as usize;
223-
assert(offset < 512) by {
224-
assert(low_bits_mask(9) == 511) by {
225-
lemma_low_bits_mask_values();
226-
};
227-
assert((va >> (level * 9)) & 511 <= 511) by (bit_vector);
228-
}
229-
// By inductive hypothesis, the recursive trace is valid
230-
assert(NodeHelper::valid_trace(va_level_to_trace_rec(va, (level + 1) as PagingLevel)));
231-
// Therefore its length is < 4
232-
assert(va_level_to_trace_rec(va, (level + 1) as PagingLevel).len() < 4);
233-
// Since we add exactly one element, the new length is still < 4
234-
assert(va_level_to_trace_rec(va, level).len() == va_level_to_trace_rec(
235-
va,
236-
(level + 1) as PagingLevel,
237-
).len() + 1);
238-
assert(va_level_to_trace_rec(va, (level + 1) as PagingLevel).len() + 1 <= 3) by {
239-
lemma_va_level_to_trace_rec_len(va, (level + 1) as PagingLevel);
240-
};
241-
}
242-
}
243-
244-
pub proof fn lemma_va_level_to_trace_valid(va: Vaddr, level: PagingLevel)
245-
requires
246-
1 <= level <= 4,
247-
ensures
248-
NodeHelper::valid_trace(va_level_to_trace(va, level)),
249-
{
250-
lemma_va_level_to_trace_rec_valid(va >> 12, level);
251-
}
252-
253201
pub proof fn lemma_va_range_get_tree_path(va: Range<Vaddr>)
254202
requires
255203
va_range_wf(va),

0 commit comments

Comments
 (0)