Skip to content

Commit ed65678

Browse files
committed
Hanging proof of new
1 parent 3318785 commit ed65678

1 file changed

Lines changed: 74 additions & 33 deletions

File tree

arch/rv32i/src/pmp.rs

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,9 +1593,21 @@ pub mod simple {
15931593

15941594
flux_rs::defs! {
15951595

1596-
// #[hide]
15971596
fn available_region_setup(i: int, old: HardwareState, new: HardwareState) -> bool {
1598-
true
1597+
let cfg = map_select(new.pmpcfg_registers, i / 4);
1598+
let region_offset = i % 4;
1599+
1600+
if region_offset == 0 {
1601+
extract(cfg, 0x00000018, 3) == 0 && !bit(cfg, 1 << 7)
1602+
} else if region_offset == 1 {
1603+
extract(cfg, 0x00001800, 11) == 0 && !bit(cfg, 1 << 15)
1604+
} else if region_offset == 2 {
1605+
extract(cfg, 0x00180000, 19) == 0 && !bit(cfg, 1 << 23)
1606+
} else if region_offset == 3 {
1607+
extract(cfg, 0x18000000, 27) == 0 && !bit(cfg, 1 << 31)
1608+
} else {
1609+
false
1610+
}
15991611
}
16001612

16011613
// forall j, j >= 0 && j < i -> available_region_setup(i, hardware_state)
@@ -1632,35 +1644,76 @@ pub mod simple {
16321644
// well revoke access to a kernel region!
16331645

16341646
#[flux_rs::sig(fn (i: usize, hw_state: &strg HardwareState[@old])
1635-
-> Result<{ i32 | all_available_regions_setup_up_to(i, new) && available_region_setup(i, old, new) }, ()>
1647+
-> Result<{ i32 | all_available_regions_setup_up_to(i + 1, new) }, ()>
16361648
requires all_available_regions_setup_up_to(i, old)
16371649
ensures hw_state: HardwareState[#new]
16381650
)]
1639-
// #[flux_rs::trusted]
16401651
fn configure_initial_pmp_idx(
16411652
i: usize,
16421653
hardware_state: &mut HardwareState,
16431654
) -> Result<i32, ()> {
1655+
// NOTE: works over PMP entries - hence the mod 4 arithmetic when
1656+
// checking a PMPCFG
1657+
1658+
let old: HardwareState = hardware_state.snapshot();
1659+
16441660
// Read the entry's CSR:
1645-
let pmpcfg_csr = csr::CSR.pmpconfig_get(i / 4);
1661+
#[flux_rs::trusted(reason = "TCB")]
1662+
#[flux_rs::sig(fn (i: usize, &HardwareState[@hw]) -> usize[bv_bv32_to_int(map_select(hw.pmpcfg_registers, i))])]
1663+
fn pmpconfig_get(i: usize, _: &HardwareState) -> usize {
1664+
csr::CSR.pmpconfig_get(i)
1665+
}
1666+
1667+
let pmpcfg_csr = pmpconfig_get(i / 4, &hardware_state);
1668+
1669+
#[flux_rs::trusted(reason = "Flux integer conversion")]
1670+
#[flux_rs::sig(fn (x: usize) -> u8[bv_bv32_to_int(extract(bv_int_to_bv32(x), 0xFF, 0))])]
1671+
fn usize_to_u8_truncate(x: usize) -> u8 {
1672+
x as u8
1673+
}
1674+
1675+
#[flux_rs::trusted(reason = "Flux integer conversion")]
1676+
// NOTE: trusted because usize == u32 here
1677+
#[flux_rs::sig(fn (x: usize) -> u32[x] requires x <= u32::MAX)]
1678+
fn usize_to_u32(x: usize) -> u32 {
1679+
x as u32
1680+
}
1681+
1682+
flux_rs::assert((i % 4) * 8 <= 24);
16461683

16471684
// Extract the entry's pmpcfg octet:
1648-
let pmpcfg: LocalRegisterCopyU8<pmpcfg_octet::Register> = LocalRegisterCopyU8::new(
1649-
pmpcfg_csr.overflowing_shr(((i % 4) * 8) as u32).0 as u8,
1650-
);
1685+
let pmpcfg: LocalRegisterCopyU8<pmpcfg_octet::Register> =
1686+
LocalRegisterCopyU8::new(usize_to_u8_truncate(super::overflowing_shr(
1687+
pmpcfg_csr,
1688+
usize_to_u32((i % 4) * 8),
1689+
)));
16511690

16521691
// As outlined above, we never touch a locked region. Thus, bail
16531692
// out if it's locked:
16541693
if pmpcfg.is_set(pmpcfg_octet::l()) {
1655-
// return Err(());
1694+
return Err(());
16561695
}
16571696

16581697
// Now that it's not locked, we can be sure that regardless of
16591698
// any ePMP bits, this region is either ignored or entirely
16601699
// denied for machine-mode access. Hence, we can change it in
16611700
// arbitrary ways without breaking our own memory access. Try to
16621701
// flip the R/W/X bits:
1663-
csr::CSR.pmpconfig_set(i / 4, pmpcfg_csr ^ (7 << ((i % 4) * 8)));
1702+
use flux_rs::bitvec::BV32;
1703+
// pmpcfg_csr ^ (7 << ((i % 4) * 8))
1704+
// change xor to (a | b) & !(a & b)
1705+
1706+
#[flux_rs::sig(fn (x: BV32, y: BV32) -> BV32[(x | y) & bv_not(x & y)])]
1707+
fn xor(x: BV32, y: BV32) -> BV32 {
1708+
(x | y) & !(x & y)
1709+
}
1710+
1711+
let rwx_bits = xor(
1712+
BV32::from(pmpcfg_csr as u32),
1713+
(BV32::from(7) << BV32::from(usize_to_u32((i % 4) * 8))),
1714+
);
1715+
let rwx_bits: u32 = rwx_bits.into();
1716+
super::pmpconfig_set(i / 4, rwx_bits as usize, hardware_state);
16641717

16651718
// Check if the CSR changed:
16661719
if pmpcfg_csr == csr::CSR.pmpconfig_get(i / 4) {
@@ -1671,8 +1724,13 @@ pub mod simple {
16711724
}
16721725

16731726
// Finally, turn the region off:
1674-
csr::CSR.pmpconfig_set(i / 4, pmpcfg_csr & !(0x18 << ((i % 4) * 8)));
1727+
let off_bits = BV32::from(pmpcfg_csr as u32)
1728+
& !(BV32::from(0x18) << BV32::from(usize_to_u32((i % 4) * 8)));
1729+
let off_bits: u32 = off_bits.into();
1730+
1731+
super::pmpconfig_set(i / 4, off_bits as usize, hardware_state);
16751732

1733+
all_available_regions_setup_up_to_step(i, &old, hardware_state);
16761734
Ok(1669)
16771735
}
16781736

@@ -1698,7 +1756,6 @@ pub mod simple {
16981756
}
16991757
let old = hardware_state.snapshot();
17001758
configure_initial_pmp_idx(i, hardware_state)?;
1701-
all_available_regions_setup_up_to_step(i, &old, hardware_state);
17021759
assert_setup(i + 1, &hardware_state);
17031760
match configure_initial_pmp_tail(i + 1, hardware_state, available_entries) {
17041761
Ok(_) => return Ok(100),
@@ -1749,14 +1806,8 @@ pub mod simple {
17491806
// Note: these pre and post conditions (all_regions_configured) seem silly
17501807
// but we need them because otherwise Flux forgets
17511808
// all state after we return
1752-
requires
1753-
all_regions_configured_correctly_up_to(i, og_hw) &&
1754-
i % 2 == 0
1755-
ensures hw_state: HardwareState{new_hw:
1756-
all_regions_configured_correctly_up_to(i + 2, new_hw)
1757-
// region_configured_correctly(er, og_hw, new_hw, i) && region_configured_correctly(or, og_hw, new_hw, i + 1)
1758-
// && all_regions_configured_correctly_up_to(i, new_hw)
1759-
}
1809+
requires all_regions_configured_correctly_up_to(i, og_hw) && i % 2 == 0
1810+
ensures hw_state: HardwareState{new_hw: all_regions_configured_correctly_up_to(i + 2, new_hw) }
17601811
)]
17611812
fn configure_region_pair(
17621813
i: usize,
@@ -1840,7 +1891,6 @@ pub mod simple {
18401891
// all state after we return
18411892
requires all_regions_configured_correctly_up_to(i, og_hw) && i % 2 == 0
18421893
ensures hw_state: HardwareState{new_hw:
1843-
// region_configured_correctly(er, og_hw, new_hw, i) &&
18441894
all_regions_configured_correctly_up_to(i + 1, new_hw)
18451895
}
18461896
)]
@@ -2249,14 +2299,8 @@ pub mod kernel_protection {
22492299
// Note: these pre and post conditions (all_regions_configured) seem silly
22502300
// but we need them because otherwise Flux forgets
22512301
// all state after we return
2252-
requires
2253-
all_regions_configured_correctly_up_to(i, og_hw) &&
2254-
i % 2 == 0
2255-
ensures hw_state: HardwareState{new_hw:
2256-
all_regions_configured_correctly_up_to(i + 2, new_hw)
2257-
// region_configured_correctly(er, og_hw, new_hw, i) && region_configured_correctly(or, og_hw, new_hw, i + 1)
2258-
// && all_regions_configured_correctly_up_to(i, new_hw)
2259-
}
2302+
requires all_regions_configured_correctly_up_to(i, og_hw) && i % 2 == 0
2303+
ensures hw_state: HardwareState{new_hw: all_regions_configured_correctly_up_to(i + 2, new_hw) }
22602304
)]
22612305
fn configure_region_pair(
22622306
i: usize,
@@ -2339,10 +2383,7 @@ pub mod kernel_protection {
23392383
// but we need them because otherwise Flux forgets
23402384
// all state after we return
23412385
requires all_regions_configured_correctly_up_to(i, og_hw) && i % 2 == 0
2342-
ensures hw_state: HardwareState{new_hw:
2343-
// region_configured_correctly(er, og_hw, new_hw, i) &&
2344-
all_regions_configured_correctly_up_to(i + 1, new_hw)
2345-
}
2386+
ensures hw_state: HardwareState{new_hw: all_regions_configured_correctly_up_to(i + 1, new_hw) }
23462387
)]
23472388
fn configure_region(
23482389
i: usize,

0 commit comments

Comments
 (0)