pub proof fn cursor_query_embedded<'rcu>(tracked
owner: &mut CursorOwner<'rcu, UserPtConfig>,
tracked regions: &mut MetaRegionOwners,
tracked guards: &mut Guards<'rcu>,
) -> res : Option<Paddr>Expand description
old(owner).inv(),old(regions).inv(),old(owner).children_not_locked(*old(guards)),old(owner).nodes_locked(*old(guards)),old(owner).metaregion_sound(*old(regions)),!old(owner).popped_too_high,ensuresfinal(owner).inv(),final(regions).inv(),final(owner).children_not_locked(*final(guards)),final(owner).nodes_locked(*final(guards)),final(owner).metaregion_sound(*final(regions)),!final(owner).popped_too_high,final(regions).slots =~= old(regions).slots,res is None
==> forall |i: usize| final(regions).slot_owners[i] == old(regions).slot_owners[i],res matches Some(
paddr,
) ==> {
&&& has_safe_slot(paddr)
&&& old(regions).slot_owners[frame_to_index(paddr)].usage == PageUsage::Frame
&&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
== (old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
+ 1) as nat
&&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
<= REF_COUNT_MAX
&&& forall |i: usize| {
i != frame_to_index(paddr)
==> final(regions).slot_owners[i] == old(regions).slot_owners[i]
}
&&& final(regions).slot_owners[frame_to_index(paddr)].self_addr
== old(regions).slot_owners[frame_to_index(paddr)].self_addr
&&& final(regions).slot_owners[frame_to_index(paddr)].usage
== old(regions).slot_owners[frame_to_index(paddr)].usage
&&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt
== old(regions).slot_owners[frame_to_index(paddr)].paths_in_pt
&&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list
== old(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list
&&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage
== old(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage
&&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr
== old(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr
},forall |c: CursorOwner<'rcu, UserPtConfig>| {
c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions))
},Mirror of crate::mm::vm_space::Cursor::query /
crate::mm::vm_space::CursorMut::query.
Exec requires invariants(owner, regions, guards). It does not
require owner.in_locked_range(): an out-of-range cursor is handled
by Cursor::query’s graceful Err (the exec requires was relaxed
accordingly; in_locked_range now only governs success, not safety).
metaregion_sound_preserves: a CursorOwner that was sound w.r.t.
the old regions is still sound w.r.t. the new regions. This
keeps VmStore::inv chainable across method calls that touch
regions.
Result Some(paddr) / None. Exec query returns
(Range<Vaddr>, Option<MappedItem>). When the inner Option is
Some(item) and the item is tracked (non-MMIO), exec
clone_item bumps rc at the leaf slot by one. The returned
Paddr here is the cloned leaf’s physical address (i.e. the
new handle the caller now logically owns); the embedding’s
[step_query] registers a fresh [FrameEntry] at that paddr
to keep accounting_inv’s rc == H + P chained. None covers
three cases: query returned Err (out of range), query returned
Ok(_, None) (cursor not at a leaf), or query returned a Some
non-tracked (MMIO) item (clone_item is a no-op for those).
In all three None subcases slot_owners is fully preserved.