Skip to content

Commit 4b4b8f5

Browse files
committed
Merge branch 'main' of github.com:asterinas/vostd into phaseII/verified
2 parents 03bb846 + 9797518 commit 4b4b8f5

32 files changed

Lines changed: 2129 additions & 1311 deletions

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ostd/specs/arch/x86_64/page_table_entry.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ impl PageTableEntry {
111111

112112
#[verifier::external_body]
113113
#[verifier::when_used_as_spec(format_flags_spec)]
114-
pub fn format_flags(prop: PageProperty) -> (res: usize)
115-
ensures res == Self::format_flags_spec(prop)
114+
pub fn format_flags(prop: PageProperty) -> usize
115+
returns Self::format_flags_spec(prop)
116116
{
117117
let flags: u8 = prop.flags.value();
118118
let priv_flags: u8 = prop.priv_flags.value();
@@ -149,8 +149,8 @@ impl PageTableEntry {
149149

150150
#[verifier::external_body]
151151
#[verifier::when_used_as_spec(format_property_spec)]
152-
pub fn format_property(entry: usize) -> (res: PageProperty)
153-
ensures res == Self::format_property_spec(entry)
152+
pub fn format_property(entry: usize) -> PageProperty
153+
returns Self::format_property_spec(entry)
154154
{
155155
let flags = entry.map_backward(&PAGE_FLAG_MAPPING)
156156
| entry.map_invert_backward(&PAGE_INVERTED_FLAG_MAPPING);
@@ -189,8 +189,8 @@ impl PageTableEntryTrait for PageTableEntry {
189189
}
190190

191191
#[inline(always)]
192-
fn default() -> (res: Self)
193-
ensures res == Self::default_spec()
192+
fn default() -> Self
193+
returns Self::default_spec()
194194
{
195195
Self { 0: 0 }
196196
}
@@ -213,8 +213,8 @@ impl PageTableEntryTrait for PageTableEntry {
213213
}
214214

215215
#[inline(always)]
216-
fn as_usize(self) -> (res: usize)
217-
ensures res == self.as_usize_spec()
216+
fn as_usize(self) -> usize
217+
returns self.as_usize_spec()
218218
{
219219
self.0 as usize
220220
}
@@ -225,8 +225,8 @@ impl PageTableEntryTrait for PageTableEntry {
225225
}
226226

227227
#[inline(always)]
228-
fn is_present(&self) -> (res: bool)
229-
ensures res == self.is_present_spec()
228+
fn is_present(&self) -> bool
229+
returns self.is_present_spec()
230230
{
231231
self.0 & PageTableFlags::PRESENT() != 0
232232
}
@@ -277,8 +277,8 @@ impl PageTableEntryTrait for PageTableEntry {
277277
}
278278

279279
#[inline(always)]
280-
fn paddr(&self) -> (res: Paddr)
281-
ensures res == self.paddr_spec()
280+
fn paddr(&self) -> Paddr
281+
returns self.paddr_spec()
282282
{
283283
self.0 & PHYS_ADDR_MASK
284284
}
@@ -289,8 +289,8 @@ impl PageTableEntryTrait for PageTableEntry {
289289
}
290290

291291
#[inline(always)]
292-
fn prop(&self) -> (res: PageProperty)
293-
ensures res == self.prop_spec()
292+
fn prop(&self) -> PageProperty
293+
returns self.prop_spec()
294294
{
295295
Self::format_property(self.0)
296296
}
@@ -301,8 +301,8 @@ impl PageTableEntryTrait for PageTableEntry {
301301
}
302302

303303
#[inline(always)]
304-
fn is_last(&self, level: PagingLevel) -> (res: bool)
305-
ensures res == self.is_last_spec(level)
304+
fn is_last(&self, level: PagingLevel) -> bool
305+
returns self.is_last_spec(level)
306306
{
307307
level == 1 || (self.0 & PageTableFlags::HUGE() != 0)
308308
}
@@ -319,4 +319,12 @@ impl PageTableEntryTrait for PageTableEntry {
319319

320320
}
321321

322+
impl PageTableEntry {
323+
/// Absent (zero) PTE has well-formed paddr for match_pte.
324+
pub axiom fn absent_pte_paddr_ok()
325+
ensures
326+
Self::new_absent_spec().paddr_spec() % crate::specs::arch::mm::PAGE_SIZE == 0,
327+
Self::new_absent_spec().paddr_spec() < crate::specs::arch::mm::MAX_PADDR;
328+
}
329+
322330
}

ostd/specs/mm/frame/frame_specs.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ impl<'a, M: AnyFrameMeta> Frame<M> {
2323
&&& regions.slot_owners[frame_to_index(paddr)].raw_count == 1
2424
&&& regions.slot_owners[frame_to_index(paddr)].self_addr == frame_to_meta(paddr)
2525
&&& has_safe_slot(paddr) // TODO: this should actually imply the first condition
26-
&&& !regions.slots.contains_key(frame_to_index(paddr)) // Whomever called `into_raw` should hold the permission.
2726
&&& regions.inv()
2827
}
2928

@@ -46,6 +45,9 @@ impl<'a, M: AnyFrameMeta> Frame<M> {
4645
&&& forall|i: usize|
4746
#![trigger new_regions.slot_owners[i], old_regions.slot_owners[i]]
4847
i != frame_to_index(paddr) ==> new_regions.slot_owners[i] == old_regions.slot_owners[i]
48+
&&& forall|i: usize|
49+
i != frame_to_index(paddr) ==>
50+
new_regions.slots.contains_key(i) == old_regions.slots.contains_key(i)
4951
&&& r.ptr.addr() == frame_to_meta(paddr)
5052
&&& r.paddr() == paddr
5153
}

ostd/specs/mm/page_table/cursor/owners.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,6 @@ impl<'rcu, C: PageTableConfig> Inv for CursorOwner<'rcu, C> {
390390
&&& self.va.index[0] == self.continuations[0].idx
391391
&&& self.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
392392
self.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
393-
&&& self.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
394-
self.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
395-
&&& self.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
396-
self.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
397393
}
398394
}
399395
}
@@ -907,6 +903,23 @@ impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
907903
self.in_locked_range(),
908904
{ admit() }
909905

906+
/// When in_locked_range and !popped_too_high, level < guard_level (from inv), hence level < NR_LEVELS.
907+
pub proof fn in_locked_range_level_lt_nr_levels(self)
908+
requires
909+
self.inv(),
910+
self.in_locked_range(),
911+
!self.popped_too_high,
912+
ensures
913+
self.level < NR_LEVELS,
914+
{
915+
assert(self.above_locked_range() ==> self.va.to_vaddr() >= self.locked_range().end);
916+
assert(self.in_locked_range() ==> self.va.to_vaddr() < self.locked_range().end);
917+
assert(self.in_locked_range() ==> !self.above_locked_range());
918+
assert(!self.popped_too_high ==> self.level < self.guard_level || self.above_locked_range());
919+
assert(self.level < self.guard_level);
920+
assert(self.guard_level <= NR_LEVELS);
921+
}
922+
910923
/// If in_locked_range() and level < guard_level, then:
911924
/// - va.align_down(page_size(level+1)) >= locked_range().start
912925
/// - va.align_down(page_size(level+1)) + page_size(level+1) <= locked_range().end

ostd/specs/mm/page_table/cursor/page_table_cursor_specs.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
1212
use crate::specs::arch::paging_consts::PagingConsts;
1313
use crate::specs::mm::page_table::cursor::owners::*;
1414
use crate::specs::mm::page_table::*;
15+
use vstd_extra::arithmetic::*;
1516

1617
use core::ops::Range;
1718

@@ -61,6 +62,14 @@ impl<C: PageTableConfig> CursorView<C> {
6162
self.query_mapping().va_range
6263
}
6364

65+
/// The VA range of the current slot when mapping a page of the given size.
66+
/// Works for both present and absent mappings: when present, equals query_range() for
67+
/// a mapping of that size; when absent, returns the aligned range that would be mapped.
68+
pub open spec fn cur_slot_range(self, size: usize) -> Range<Vaddr> {
69+
let start = nat_align_down(self.cur_va as nat, size as nat) as Vaddr;
70+
start..(start as nat + size as nat) as Vaddr
71+
}
72+
6473
/// This predicate specifies the behavior of the `query` method. It states that the current item
6574
/// in the page table matches the given item, mapped at the resulting virtual address range.
6675
pub open spec fn query_item_spec(self, item: C::Item) -> Option<Range<Vaddr>>
@@ -175,7 +184,7 @@ impl<C: PageTableConfig> CursorView<C> {
175184
/// a new large mapping.
176185
pub open spec fn map_spec(self, paddr: Paddr, size: usize, prop: PageProperty) -> Self {
177186
let new = Mapping {
178-
va_range: self.query_range(),
187+
va_range: self.cur_slot_range(size),
179188
pa_range: paddr..(paddr + size) as usize,
180189
page_size: size,
181190
property: prop,
@@ -191,7 +200,7 @@ impl<C: PageTableConfig> CursorView<C> {
191200
///
192201
pub open spec fn map_simple(self, paddr: Paddr, size: usize, prop: PageProperty) -> Self {
193202
let new = Mapping {
194-
va_range: self.query_range(),
203+
va_range: self.cur_slot_range(size),
195204
pa_range: paddr..(paddr + size) as usize,
196205
page_size: size,
197206
property: prop,
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
use vstd::prelude::*;
2+
3+
use vstd_extra::ownership::*;
4+
5+
use crate::mm::frame::*;
6+
use crate::mm::page_prop::PageProperty;
7+
use crate::mm::page_table::*;
8+
use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
9+
use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
10+
use crate::specs::arch::paging_consts::PagingConsts;
11+
use crate::specs::mm::frame::meta_owners::MetaSlotOwner;
12+
use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
13+
14+
verus! {
15+
16+
impl<C: PageTableConfig> OwnerOf for Child<C> {
17+
type Owner = EntryOwner<C>;
18+
19+
open spec fn wf(self, owner: Self::Owner) -> bool {
20+
match self {
21+
Self::PageTable(node) => {
22+
&&& owner.is_node()
23+
&&& node.ptr.addr() == owner.node.unwrap().meta_perm.addr()
24+
&&& node.index() == frame_to_index(meta_to_frame(node.ptr.addr()))
25+
},
26+
Self::Frame(paddr, level, prop) => {
27+
&&& owner.is_frame()
28+
&&& owner.frame.unwrap().mapped_pa == paddr
29+
&&& owner.frame.unwrap().prop == prop
30+
&&& level == owner.parent_level
31+
},
32+
Self::None => owner.is_absent(),
33+
}
34+
}
35+
}
36+
37+
38+
impl<'a, C: PageTableConfig> OwnerOf for ChildRef<'a, C> {
39+
type Owner = EntryOwner<C>;
40+
41+
open spec fn wf(self, owner: Self::Owner) -> bool {
42+
match self {
43+
Self::PageTable(node) => {
44+
&&& owner.is_node()
45+
&&& node.inner.0.ptr.addr() == owner.node.unwrap().meta_perm.addr()
46+
},
47+
Self::Frame(paddr, level, prop) => {
48+
&&& owner.is_frame()
49+
&&& owner.frame.unwrap().mapped_pa == paddr
50+
&&& owner.frame.unwrap().prop == prop
51+
},
52+
Self::None => owner.is_absent(),
53+
}
54+
}
55+
}
56+
57+
impl<C: PageTableConfig> Child<C> {
58+
59+
pub open spec fn get_node(self) -> Option<PageTableNode<C>> {
60+
match self {
61+
Self::PageTable(node) => Some(node),
62+
_ => None,
63+
}
64+
}
65+
66+
pub open spec fn get_frame_tuple(self) -> Option<(Paddr, PagingLevel, PageProperty)> {
67+
match self {
68+
Self::Frame(paddr, level, prop) => Some((paddr, level, prop)),
69+
_ => None,
70+
}
71+
}
72+
73+
pub open spec fn into_pte_frame_spec(self, tuple: (Paddr, PagingLevel, PageProperty)) -> C::E {
74+
let (paddr, level, prop) = tuple;
75+
C::E::new_page_spec(paddr, level, prop)
76+
}
77+
78+
79+
pub open spec fn into_pte_none_spec(self) -> C::E {
80+
C::E::new_absent_spec()
81+
}
82+
83+
84+
pub open spec fn from_pte_spec(pte: C::E, level: PagingLevel, regions: MetaRegionOwners) -> Self {
85+
if !pte.is_present() {
86+
Self::None
87+
} else if pte.is_last(level) {
88+
Self::Frame(pte.paddr(), level, pte.prop())
89+
} else {
90+
Self::PageTable(PageTableNode::from_raw_spec(pte.paddr()))
91+
}
92+
}
93+
94+
pub open spec fn from_pte_frame_spec(pte: C::E, level: PagingLevel) -> Self {
95+
Self::Frame(pte.paddr(), level, pte.prop())
96+
}
97+
98+
99+
pub open spec fn from_pte_pt_spec(paddr: Paddr, regions: MetaRegionOwners) -> Self {
100+
Self::PageTable(PageTableNode::from_raw_spec(paddr))
101+
}
102+
103+
pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
104+
&&& owner.inv()
105+
&&& regions.inv()
106+
&&& self.wf(owner)
107+
&&& owner.relate_region(regions)
108+
&&& owner.in_scope
109+
}
110+
}
111+
112+
impl<C: PageTableConfig> ChildRef<'_, C> {
113+
pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
114+
&&& owner.inv()
115+
&&& regions.inv()
116+
&&& self.wf(owner)
117+
&&& owner.relate_region(regions)
118+
&&& !owner.in_scope
119+
}
120+
}
121+
122+
impl<C: PageTableConfig> EntryOwner<C> {
123+
124+
pub open spec fn from_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
125+
if self.is_node() {
126+
let index = frame_to_index(self.meta_slot_paddr().unwrap());
127+
let old_slot = regions.slot_owners[index];
128+
let new_slot = MetaSlotOwner {
129+
raw_count: 0usize,
130+
..old_slot
131+
};
132+
MetaRegionOwners {
133+
slots: regions.slots.insert(index, self.node.unwrap().meta_perm.points_to),
134+
slot_owners: regions.slot_owners.insert(index, new_slot),
135+
}
136+
} else {
137+
regions
138+
}
139+
}
140+
141+
pub open spec fn into_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
142+
if self.is_node() {
143+
let index = frame_to_index(self.meta_slot_paddr().unwrap());
144+
let old_slot = regions.slot_owners[index];
145+
let new_slot = MetaSlotOwner {
146+
raw_count: (old_slot.raw_count + 1) as usize,
147+
..old_slot
148+
};
149+
MetaRegionOwners {
150+
slots: regions.slots,
151+
slot_owners: regions.slot_owners.insert(index, new_slot),
152+
..regions
153+
}
154+
} else {
155+
regions
156+
}
157+
}
158+
159+
pub open spec fn into_pte_owner_spec(self) -> EntryOwner<C> {
160+
EntryOwner {
161+
in_scope: false,
162+
..self
163+
}
164+
}
165+
166+
pub open spec fn from_pte_owner_spec(self) -> EntryOwner<C> {
167+
EntryOwner {
168+
in_scope: true,
169+
..self
170+
}
171+
}
172+
173+
/// This is equivalent to the other `invariants` relations, combining the `inv` predicates for each
174+
/// object and the well-formedness relations between them.
175+
pub open spec fn pte_invariants(self, pte: C::E, regions: MetaRegionOwners) -> bool {
176+
&&& self.inv()
177+
&&& regions.inv()
178+
&&& self.match_pte(pte, self.parent_level)
179+
&&& self.relate_region(regions)
180+
&&& !self.in_scope
181+
}
182+
183+
}
184+
185+
} // verus!

0 commit comments

Comments
 (0)