Skip to content

Commit 57ee907

Browse files
committed
Add a CI and some proof fixes
1 parent da7fcec commit 57ee907

File tree

7 files changed

+218
-66
lines changed

7 files changed

+218
-66
lines changed

.github/workflows/ci.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Proof
2+
3+
on:
4+
# Run this action every day
5+
schedule:
6+
- cron: '30 18 * * *'
7+
pull_request:
8+
push:
9+
10+
# cancel in-progress job when a new push is performed
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
build:
17+
strategy:
18+
matrix:
19+
version: [5.2.0]
20+
21+
runs-on: ubuntu-22.04
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
repository: rems-project/cerberus
27+
28+
- name: System dependencies (ubuntu)
29+
run: |
30+
sudo apt install build-essential libgmp-dev z3 opam
31+
32+
- name: Restore cached opam
33+
id: cache-opam-restore
34+
uses: actions/cache/restore@v4
35+
with:
36+
path: ~/.opam
37+
key: ${{ matrix.version }}
38+
39+
- name: Setup opam
40+
if: steps.cache-opam-restore.outputs.cache-hit != 'true'
41+
run: |
42+
opam init --yes --no-setup --shell=sh --compiler=${{ matrix.version }}
43+
opam switch ${{ matrix.version }}
44+
eval $(opam env --switch=${{ matrix.version }})
45+
opam install --deps-only --yes ./cerberus.opam ./cerberus-lib.opam ./cn.opam
46+
opam install --yes z3
47+
48+
- name: Save cached opam
49+
if: steps.cache-opam-restore.outputs.cache-hit != 'true'
50+
id: cache-opam-save
51+
uses: actions/cache/save@v4
52+
with:
53+
path: ~/.opam
54+
key: ${{ steps.cache-opam-restore.outputs.cache-primary-key }}
55+
56+
- name: Install Cerberus
57+
run: |
58+
opam switch ${{ matrix.version }}
59+
eval $(opam env --switch=${{ matrix.version }})
60+
opam pin --yes --no-action add cerberus-lib .
61+
opam pin --yes --no-action add cerberus .
62+
opam install --yes cerberus
63+
64+
- name: Install CN
65+
run: |
66+
opam switch ${{ matrix.version }}
67+
eval $(opam env --switch=${{ matrix.version }})
68+
opam pin --yes --no-action add cn .
69+
opam install --yes cn
70+
71+
# - name: Download cvc5 release
72+
# uses: robinraju/release-downloader@v1
73+
# with:
74+
# repository: cvc5/cvc5
75+
# tag: cvc5-1.1.2
76+
# fileName: cvc5-Linux-static.zip
77+
78+
# - name: Unzip and install cvc5
79+
# run: |
80+
# unzip cvc5-Linux-static.zip
81+
# chmod +x cvc5-Linux-static/bin/cvc5
82+
# sudo cp cvc5-Linux-static/bin/cvc5 /usr/local/bin/
83+
84+
- name: Checkout this repo
85+
uses: actions/checkout@v4
86+
with:
87+
path: buddy-alloc
88+
89+
- name: Run CN Proof
90+
run: |
91+
opam switch ${{ matrix.version }}
92+
eval $(opam env --switch=${{ matrix.version }})
93+
cd buddy-alloc && ./proof.sh

defs.h

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ function (boolean) vmemmap_wf (u64 page_index,
176176
&& (page_group_ok(page_index, vmemmap, pool))
177177
}
178178
179+
function (boolean) eq_t(pointer x, pointer y) {
180+
ptr_eq(x,y) || !addr_eq(x,y)
181+
}
182+
179183
function (boolean) vmemmap_l_wf (u64 page_index, i64 physvirt_offset,
180184
pointer virt_ptr,
181185
map <u64, struct hyp_page> vmemmap, map <u64, struct list_head> APs,
@@ -212,7 +216,11 @@ function (boolean) vmemmap_l_wf (u64 page_index, i64 physvirt_offset,
212216
// there is no self-loop case for this node type, as it is cleared unless it is
213217
// present in the per-order free list - TODO delete?
214218
let nonempty_clause = (prev != self_node_pointer) && (next != self_node_pointer);
215-
(prev_clause && next_clause)
219+
let eq_testable = eq_t(prev, self_node_pointer)
220+
&& eq_t(prev, pool_free_area_pointer)
221+
&& eq_t(next, prev)
222+
&& eq_t(next, pool_free_area_pointer);
223+
(prev_clause && next_clause && eq_testable)
216224
}
217225
218226
@@ -265,7 +273,7 @@ function (boolean) hyp_pool_wf (pointer pool_pointer, struct hyp_pool pool,
265273
(range_start < range_end)
266274
&& (range_end < shift_left(1u64, 52u64))
267275
&& (physvirt_offset < (i64) range_start) // use '<='
268-
&& (mod((u64) physvirt_offset, (page_size ())) == 0u64)
276+
&& mod((u64) physvirt_offset, page_size ()) == 0u64
269277
&& (((range_start / (page_size ())) * (page_size ())) == range_start)
270278
&& (((range_end / (page_size ())) * (page_size ())) == range_end)
271279
&& (pool.max_order <= (max_order ()))
@@ -305,9 +313,7 @@ predicate void Page (pointer vbase, boolean guard, u8 order)
305313
}
306314
else {
307315
let length = page_size_of_order(order);
308-
let vbaseI = (u64) vbase;
309-
take Bytes = each (u64 i; (vbaseI <= i) && (i < (vbaseI + length)))
310-
{Byte(array_shift<char>(NULL, i))};
316+
take Bytes = each (u64 i; 0u64 <= i && i < length) {Byte(array_shift<char>(vbase, i))};
311317
return;
312318
}
313319
}
@@ -318,21 +324,18 @@ predicate void ZeroPage (pointer vbase, boolean guard, u8 order)
318324
return;
319325
}
320326
else {
321-
let length = page_size_of_order(order);
322-
let vbaseI = ((u64) vbase);
323-
take Bytes = each (u64 i; (vbaseI <= i) && (i < (vbaseI + length)))
324-
{ByteV(array_shift<char>(NULL, i), 0u8)};
327+
let length = sizeof<struct list_head>;
328+
take B1 = each (u64 i; 0u64 <= i && i < length) {ByteV(array_shift<char>(vbase, i), 0u8)};
329+
take B2 = each (u64 i; length <= i && i < page_size_of_order(order)) {ByteV(array_shift<char>(vbase, i), 0u8)};
325330
return;
326331
}
327332
}
328333
329-
predicate void AllocatorPageZeroPart (pointer zero_start, u8 order)
334+
predicate void AllocatorPageZeroPart (pointer vbase, u8 order)
330335
{
331-
let start = (u64) zero_start;
332336
let region_length = page_size_of_order(order);
333-
let length = region_length - sizeof<struct list_head>;
334-
take Bytes = each (u64 i; (start <= i) && (i < (start + length)))
335-
{ByteV(array_shift<char>(NULL, i), 0u8)};
337+
take Bytes = each (u64 i; sizeof<struct list_head> <= i && i < region_length)
338+
{ByteV(array_shift<char>(vbase, i), 0u8)};
336339
return;
337340
}
338341
@@ -347,9 +350,8 @@ predicate struct list_head AllocatorPage
347350
return (todo_default_list_head ());
348351
}
349352
else {
350-
let zero_start = array_shift<struct list_head>(vbase, 1u8);
351-
take ZeroPart = AllocatorPageZeroPart (zero_start, order);
352353
take Node = Owned<struct list_head>(vbase);
354+
take ZeroPart = AllocatorPageZeroPart (vbase, order);
353355
return Node;
354356
}
355357
}

lemmas.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,12 @@ lemma page_size_of_order2(u8 order) // unsigned int
160160
161161
lemma struct_list_head_to_bytes(pointer node) // struct list_head *
162162
requires take Node = Owned<struct list_head>(node);
163-
ensures take B = each (u64 i; ((u64) node) <= i && i < (((u64) node) + (sizeof<struct list_head>))){Byte(array_shift<char>(NULL, i))};
163+
ensures take B = each (u64 i; 0u64 <= i && i < sizeof<struct list_head>){Byte(array_shift<char>(node, i))};
164164
165165
166166
lemma bytes_to_struct_list_head(pointer node, // struct list_head *
167167
u8 order)
168-
requires let length = page_size_of_order(order) ;
169-
let nodeI = ((u64) node) ;
170-
take B = each (u64 i; (nodeI <= i) && (i < (nodeI + length))) {ByteV(array_shift<char>(NULL, i), 0u8)};
171-
ensures take Node = Owned<struct list_head>(node) ;
172-
take BR = each (u64 i; (nodeI + (sizeof<struct list_head>)) <= i && i < (nodeI + length)){ByteV(array_shift<char>(NULL, i), 0u8)};
168+
requires take B = each (u64 i; 0u64 <= i && i < sizeof<struct list_head>) {ByteV(array_shift<char>(node, i), 0u8)};
169+
ensures take Node = Owned<struct list_head>(node);
173170
174171
@*/

memory.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ extern struct hyp_page *__hyp_vmemmap;
3535

3636
static inline void *hyp_phys_to_virt(phys_addr_t phys)
3737
/*@ accesses hyp_physvirt_offset; cn_virt_base; @*/
38-
/*@ requires let virt = phys - (u64) hyp_physvirt_offset; @*/
38+
/*@ requires has_alloc_id(cn_virt_base); @*/
39+
/*@ requires let virt = cn__hyp_va(cn_virt_base, hyp_physvirt_offset, phys); @*/
3940
/*@ ensures {hyp_physvirt_offset} unchanged; @*/
40-
/*@ ensures (u64) return == virt; @*/
41+
/*@ ensures {cn_virt_base} unchanged; @*/
42+
/*@ ensures ptr_eq(return, virt); @*/
4143
{
4244
return CN_COPY_ALLOC_ID(__hyp_va(phys), cn_virt_base);
4345
}
@@ -73,9 +75,13 @@ function (u64) max_pfn ()
7375

7476
static inline u64 hyp_page_to_pfn(struct hyp_page *page)
7577
/*@ accesses __hyp_vmemmap; @*/
78+
/*@ requires has_alloc_id(page); @*/
79+
/*@ requires has_alloc_id(__hyp_vmemmap); @*/
80+
/*@ requires (alloc_id) page == (alloc_id) __hyp_vmemmap; @*/
81+
/*@ requires mod((u64)__hyp_vmemmap, sizeof<struct hyp_page>) == 0u64; @*/
7682
/*@ requires let offs = ((u64) page) - ((u64) __hyp_vmemmap); @*/
7783
/*@ requires offs <= max_pfn () * (sizeof<struct hyp_page>); @*/
78-
/*@ requires mod(offs, sizeof<struct hyp_page>) == 0u64; @*/
84+
/*@ requires mod((u64)page, sizeof<struct hyp_page>) == 0u64; @*/
7985
/*@ ensures return == offs / (sizeof<struct hyp_page>); @*/
8086
/*@ ensures {__hyp_vmemmap} unchanged; @*/
8187
{

0 commit comments

Comments
 (0)