зеркало из https://github.com/microsoft/Komodo.git
264 строки
7.9 KiB
Plaintext
264 строки
7.9 KiB
Plaintext
include {:verbatim} "kom_common.i.dfy"
|
|
include {:verbatim} "bitvectors.i.dfy"
|
|
include {:verbatim} "pagedb.i.dfy"
|
|
include "ARMdecls.sdfy"
|
|
|
|
procedure page_paddr_impl(out operand phys:reg, operand pagenr:reg, out operand tmp:reg)
|
|
reads
|
|
globals;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
// NB: @phys == @pagenr is supported
|
|
@phys != @tmp;
|
|
@pagenr != @tmp;
|
|
@phys != OSP;
|
|
@tmp != OSP;
|
|
validPageNr(pagenr);
|
|
ensures
|
|
//SmcProcedureInvariant(old(this), this);
|
|
phys == page_paddr(old(pagenr));
|
|
PageAligned(phys);
|
|
{
|
|
assert pagenr < KOM_SECURE_NPAGES;
|
|
lemma_LeftShift12(pagenr);
|
|
LSL(phys, pagenr, 12);
|
|
assert phys == old(pagenr) * PAGESIZE;
|
|
|
|
LDRglobaladdr(tmp, SecurePhysBaseOp());
|
|
LDRglobal(tmp, SecurePhysBaseOp(), tmp, 0);
|
|
assert WordAligned(tmp);
|
|
ADD(phys, phys, tmp);
|
|
}
|
|
|
|
procedure paddr_page_impl(out operand pagenr:reg, operand phys:reg, out operand tmp:reg)
|
|
reads
|
|
globals;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
// NB: @phys == @pagenr is supported
|
|
@phys != @tmp;
|
|
@pagenr != @tmp;
|
|
@tmp != OSP;
|
|
@pagenr != OSP;
|
|
PageAligned(phys);
|
|
SecurePhysBase() <= phys < SecurePhysBase() + KOM_SECURE_RESERVE;
|
|
ensures
|
|
//SmcProcedureInvariant(old(this), this);
|
|
pagenr == paddr_page(old(phys));
|
|
validPageNr(pagenr);
|
|
{
|
|
LDRglobaladdr(tmp, SecurePhysBaseOp());
|
|
LDRglobal(tmp, SecurePhysBaseOp(), tmp, 0);
|
|
assert WordAligned(tmp);
|
|
SUB(pagenr,phys,tmp);
|
|
|
|
ghost var oldpagenr := pagenr;
|
|
LSR(pagenr, pagenr, 12);
|
|
lemma_RightShift12(oldpagenr);
|
|
assert pagenr == oldpagenr / PAGESIZE;
|
|
}
|
|
|
|
procedure page_monvaddr_impl(out operand virt:reg, operand pagenr:reg, out operand tmp:reg)
|
|
reads
|
|
globals;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
// NB: @pagenr == @virt is supported
|
|
@pagenr != @tmp;
|
|
@virt != @tmp;
|
|
@virt != OSP;
|
|
@tmp != OSP;
|
|
validPageNr(pagenr);
|
|
ensures
|
|
//SmcProcedureInvariant(old(this), this);
|
|
virt == page_monvaddr(old(pagenr));
|
|
{
|
|
page_paddr_impl(virt, pagenr, tmp);
|
|
ADD(virt, virt, const(KOM_DIRECTMAP_VBASE));
|
|
}
|
|
|
|
procedure stack_nonvolatiles(ghost stack_bytes:int) returns (ghost stack_bytes_ret:int)
|
|
reads
|
|
r4; r5; r6; r7; r8; r9; r10; r11; r12; lr;
|
|
modifies
|
|
sp; mem;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
stack_bytes >= 40;
|
|
StackBytesRemaining(this,stack_bytes);
|
|
ensures
|
|
sp == old(sp-40);
|
|
|
|
//preserves registers
|
|
//RegPreservingExcept(old(this), this, set(@sp));
|
|
|
|
// pushes r4-r11, sp, lr
|
|
MemContents(this.m, sp) == old(r12);
|
|
MemContents(this.m, sp+4) == old(r11);
|
|
MemContents(this.m, sp+8) == old(r10);
|
|
MemContents(this.m, sp+12) == old(r9);
|
|
MemContents(this.m, sp+16) == old(r8);
|
|
MemContents(this.m, sp+20) == old(r7);
|
|
MemContents(this.m, sp+24) == old(r6);
|
|
MemContents(this.m, sp+28) == old(r5);
|
|
MemContents(this.m, sp+32) == old(r4);
|
|
MemContents(this.m, sp+36) == old(lr);
|
|
|
|
//GlobalsInvariant(old(this),this);
|
|
//BankedRegsInvariant(old(this),this);
|
|
//SRegsInvariant(old(this),this);
|
|
NonStackMemPreserving(old(this),this);
|
|
ParentStackPreserving(old(this),this);
|
|
|
|
stack_bytes_ret == stack_bytes-40;
|
|
StackBytesRemaining(this,stack_bytes_ret);
|
|
{
|
|
SUB(sp, sp, 40);
|
|
|
|
STR(lr, sp, 36);
|
|
STR(r4, sp, 32);
|
|
STR(r5, sp, 28);
|
|
STR(r6, sp, 24);
|
|
STR(r7, sp, 20);
|
|
STR(r8, sp, 16);
|
|
STR(r9, sp, 12);
|
|
STR(r10, sp, 8);
|
|
STR(r11, sp, 4);
|
|
STR(r12, sp, 0);
|
|
|
|
stack_bytes_ret := stack_bytes - 40;
|
|
}
|
|
|
|
procedure unstack_nonvolatiles(ghost stack_bytes:int) returns (ghost stack_bytes_ret:int)
|
|
reads
|
|
mem;
|
|
modifies
|
|
r4; r5; r6; r7; r8; r9; r10; r11; r12; lr; sp;
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
isUInt32(sp + 40);
|
|
sp + 40 <= StackBase();
|
|
StackBytesRemaining(this, stack_bytes);
|
|
ensures
|
|
sp == old(sp+40);
|
|
|
|
// fcall argument regs preserved.
|
|
//r0 == old(r0);
|
|
//r1 == old(r1);
|
|
//r2 == old(r2);
|
|
//r3 == old(r3);
|
|
|
|
// pop lr, r4-r11 from stack.
|
|
lr == old(MemContents(this.m, sp+36));
|
|
r4 == old(MemContents(this.m, sp+32));
|
|
r5 == old(MemContents(this.m, sp+28));
|
|
r6 == old(MemContents(this.m, sp+24));
|
|
r7 == old(MemContents(this.m, sp+20));
|
|
r8 == old(MemContents(this.m, sp+16));
|
|
r9 == old(MemContents(this.m, sp+12));
|
|
r10 == old(MemContents(this.m, sp+8));
|
|
r11 == old(MemContents(this.m, sp+4));
|
|
r12 == old(MemContents(this.m, sp));
|
|
|
|
//AllMemInvariant(old(this),this);
|
|
//BankedRegsInvariant(old(this),this);
|
|
//SRegsInvariant(old(this),this);
|
|
|
|
stack_bytes_ret == stack_bytes + 40;
|
|
StackBytesRemaining(this, stack_bytes_ret);
|
|
{
|
|
//pop r12 down to r4 from stack
|
|
LDR(r12, sp, 0);
|
|
LDR(r11, sp, 4);
|
|
LDR(r10, sp, 8);
|
|
LDR(r9, sp, 12);
|
|
LDR(r8, sp, 16);
|
|
LDR(r7, sp, 20);
|
|
LDR(r6, sp, 24);
|
|
LDR(r5, sp, 28);
|
|
LDR(r4, sp, 32);
|
|
|
|
//pop link register from stack
|
|
LDR(lr, sp, 36);
|
|
ADD(sp, sp, 40);
|
|
|
|
stack_bytes_ret := stack_bytes + 40;
|
|
}
|
|
|
|
procedure load_page_type(
|
|
operand pagenr:reg,
|
|
operand pagedb_base:addr,
|
|
out operand offset:reg,
|
|
out operand pgtype:reg,
|
|
ghost pagedb:PageDb)
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
validPageNr(pagenr);
|
|
pagedb_base == AddressOfGlobal(PageDb());
|
|
@pgtype != OSP && @offset != OSP && @offset != @pagedb_base;
|
|
validPageDb(pagedb);
|
|
pageDbCorresponds(this.m, pagedb);
|
|
reads
|
|
globals;
|
|
ensures
|
|
pgtype == pageDbEntryTypeVal(pagedb[old(pagenr)]);
|
|
@offset != @pgtype ==> offset == G_PAGEDB_ENTRY(old(pagenr));
|
|
|
|
{
|
|
lemma_LeftShift3(pagenr);
|
|
LSL(offset, pagenr, const(PAGEDB_ENTRY_SHIFT));
|
|
assert offset == G_PAGEDB_ENTRY(old(pagenr)) + PAGEDB_ENTRY_TYPE;
|
|
LDRglobal(pgtype, PageDb(), pagedb_base, offset);
|
|
|
|
reveal pageDbEntryCorresponds;
|
|
PageDbCorrespondsImpliesEntryCorresponds(this.m, pagedb, old(pagenr));
|
|
extractPageDbToAbstractOne(this.m, old(pagenr), PAGEDB_ENTRY_TYPE);
|
|
}
|
|
|
|
procedure update_pagedb_entry(
|
|
ghost page:PageNr,
|
|
ghost gentry:PageDbEntry,
|
|
inout operand entry:reg,
|
|
operand typeword:reg,
|
|
operand as_va:reg,
|
|
operand pagedb_base:reg)
|
|
requires/ensures
|
|
SaneState(this);
|
|
requires
|
|
validPageNr(page);
|
|
wellFormedPageDbEntry(gentry);
|
|
gentry is PageDbEntryTyped;
|
|
as_va == page_monvaddr(gentry.addrspace);
|
|
typeword == pageDbEntryTypeVal(gentry);
|
|
entry == G_PAGEDB_ENTRY(page);
|
|
pagedb_base == AddressOfGlobal(PageDb());
|
|
@entry != @as_va && @entry != @pagedb_base;
|
|
modifies
|
|
globals;
|
|
ensures
|
|
SmcProcedureInvariant(old(this), this);
|
|
GlobalsPreservingExcept(old(this), this, set(PageDb()));
|
|
pageDbEntryCorresponds(gentry, extractPageDbEntry(this.m, page));
|
|
forall p :: validPageNr(p) && p != page
|
|
==> extractPageDbEntry(old(this).m, p) == extractPageDbEntry(this.m, p);
|
|
{
|
|
STRglobal(typeword, PageDb(), pagedb_base, entry);
|
|
assert GlobalWord(this.m, PageDb(), G_PAGEDB_ENTRY(page)
|
|
+ PAGEDB_ENTRY_TYPE) == old(typeword);
|
|
ADD(entry, entry, const(PAGEDB_ENTRY_ADDRSPACE));
|
|
assert entry == G_PAGEDB_ENTRY(page) + PAGEDB_ENTRY_ADDRSPACE;
|
|
STRglobal(as_va, PageDb(), pagedb_base, entry);
|
|
assert GlobalWord(this.m, PageDb(), G_PAGEDB_ENTRY(page)
|
|
+ PAGEDB_ENTRY_ADDRSPACE) == old(as_va);
|
|
|
|
extractPageDbToAbstract(this.m, page);
|
|
assert extractPageDbEntry(this.m, page) == seq(old(typeword), old(as_va));
|
|
reveal pageDbEntryCorresponds;
|
|
}
|