Skip to content

Commit 9923af1

Browse files
committed
Pull master
2 parents 44d567f + 49ae3dd commit 9923af1

13 files changed

Lines changed: 1780 additions & 623 deletions

File tree

‎arch/cortex-m/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod syscall;
3232
pub mod systick;
3333

3434
pub mod mpu;
35+
mod tcb;
3536

3637
// These constants are defined in the linker script.
3738
extern "C" {

‎arch/cortex-m/src/mpu.rs‎

Lines changed: 22 additions & 276 deletions
Original file line numberDiff line numberDiff line change
@@ -12,260 +12,16 @@ use core::num::NonZeroUsize;
1212
use flux_support::capability::MpuEnabledCapability;
1313
use kernel::utilities::StaticRef;
1414

15-
use flux_support::register_bitfields;
15+
use crate::tcb::math::*;
16+
use crate::tcb::theorems::*;
17+
use flux_support::register_bitfields_u32;
1618
use flux_support::*;
1719
use kernel::platform::mpu::{self, RegionDescriptor};
1820
use kernel::utilities::cells::OptionalCell;
1921
use kernel::utilities::math;
2022
use kernel::utilities::registers::interfaces::{Readable, Writeable};
2123
use kernel::utilities::registers::{FieldValue, ReadOnly, ReadWrite};
2224

23-
/* extern specs have to live here because the defs for these specs are defined here */
24-
25-
#[flux_rs::extern_spec]
26-
impl usize {
27-
#[flux_rs::sig(fn (num: usize) -> usize{r: r >= num && pow2(r) && half_max(r)} requires half_max(num))]
28-
fn next_power_of_two(self) -> usize;
29-
30-
#[flux_rs::sig(fn (num: usize) -> bool[pow2(num)])]
31-
fn is_power_of_two(self) -> bool;
32-
33-
#[sig(fn(num: usize{num <= u32::MAX}) -> u32{r: r <= 32 && (num > 0 => r < 32) && aligned(num, to_pow2(r)) && (aligned(num, 2) => r > 0)})]
34-
fn trailing_zeros(self) -> u32;
35-
}
36-
37-
/* a bunch of theorems and proof code */
38-
39-
#[flux_rs::reveal(aligned)]
40-
#[flux_rs::sig(fn (usize[@x], usize[@y]) requires x > 0 && aligned(x, y) ensures x >= y)]
41-
fn theorem_aligned_ge(_x: usize, _y: usize) {}
42-
43-
#[flux_rs::reveal(aligned)]
44-
#[flux_rs::sig(fn (usize[@x], usize[@y]) requires x == 0 && y > 0 ensures aligned(x, y))]
45-
fn theorem_aligned0(_x: usize, _y: usize) {}
46-
47-
#[flux_rs::reveal(to_pow2)]
48-
#[flux_rs::sig(fn (x: usize) requires x > 0 && x < 32 ensures to_pow2(x) > 1)]
49-
fn theorem_to_pow2_gt1(x: usize) {}
50-
51-
#[flux_rs::reveal(pow2, to_pow2)]
52-
#[flux_rs::sig(fn (usize[@n]) requires n < 32 ensures pow2(to_pow2(n)))]
53-
fn theorem_to_pow2_is_pow2(_n: usize) {}
54-
55-
#[flux_rs::trusted(reason = "math")]
56-
#[flux_rs::sig(fn (usize[@x], usize[@y], usize[@z]) requires aligned(x, y) && z <= y && pow2(y) && pow2(z) ensures aligned(x, z))]
57-
fn theorem_pow2_le_aligned(x: usize, y: usize, z: usize) {}
58-
59-
#[flux_rs::trusted(reason = "math")]
60-
#[flux_rs::sig(fn (r:usize) requires pow2(r) && r >= 8 ensures octet(r))]
61-
fn theorem_pow2_octet(_n: usize) {}
62-
63-
#[flux_rs::trusted(reason = "math")]
64-
#[flux_rs::sig(fn (n:usize) requires pow2(n) && n >= 4 ensures pow2(n / 2))]
65-
fn theorem_pow2_div2_pow2(_n: usize) {}
66-
67-
#[flux_rs::reveal(octet)]
68-
#[flux_rs::sig(fn (r:usize) requires octet(r) ensures 8 * (r / 8) == r)]
69-
fn theorem_div_octet(_n: usize) {}
70-
71-
#[flux_rs::reveal(aligned)]
72-
#[flux_rs::sig(fn (x: usize, y: usize) requires aligned(x, y) ensures aligned(x + y, y))]
73-
fn theorem_aligned_plus_aligned_to_is_aligned(_x: usize, _y: usize) {}
74-
75-
#[flux_rs::trusted(reason = "math")]
76-
#[flux_rs::sig(fn (x: usize, y: usize) requires y >= 32 && pow2(y) && aligned(x, y) ensures least_five_bits(bv32(x)) == 0)]
77-
fn theorem_aligned_value_ge32_lowest_five_bits0(x: usize, y: usize) {}
78-
79-
#[flux_rs::reveal(octet, first_subregion_from_logical)]
80-
#[flux_rs::sig(fn (rstart: FluxPtr, rsize: usize, astart: FluxPtr, asize: usize)
81-
requires rstart == astart && rsize == asize && rsize >= 32
82-
ensures first_subregion_from_logical(rstart, rsize, astart, asize) == 0
83-
)]
84-
fn theorem_first_subregion_0(rstart: FluxPtr, rsize: usize, astart: FluxPtr, asize: usize) {}
85-
86-
#[flux_rs::reveal(octet, last_subregion_from_logical)]
87-
#[flux_rs::sig(fn (rstart: FluxPtr, rsize: usize, astart: FluxPtr, asize: usize)
88-
requires rstart == astart && rsize == asize && rsize >= 32 && octet(rsize)
89-
ensures last_subregion_from_logical(rstart, rsize, astart, asize) == 7
90-
)]
91-
fn theorem_last_subregion_7(rstart: FluxPtr, rsize: usize, astart: FluxPtr, asize: usize) {}
92-
93-
#[flux_rs::reveal(octet, subregions_disabled_bit_set)]
94-
#[flux_rs::sig(fn (&FieldValueU32<RegionAttributes::Register>[@rasr])
95-
ensures
96-
enabled_srd_mask(0, 7) == 255 &&
97-
disabled_srd_mask(0, 7) == 0 &&
98-
subregions_disabled_bit_set(rasr.value, 0, 7)
99-
)]
100-
fn theorem_subregions_disabled_bit_set_0_7(attributes: &FieldValueU32<RegionAttributes::Register>) {
101-
}
102-
103-
#[flux_rs::sig(fn (&FieldValueU32<RegionAttributes::Register>[@rasr])
104-
requires
105-
subregions_enabled_bit_set(rasr.value, 0, 7)
106-
ensures
107-
enabled_srd_mask(0, 7) == 255 &&
108-
disabled_srd_mask(0, 7) == 0
109-
)]
110-
fn theorem_subregions_enabled_bit_set_0_7(attributes: &FieldValueU32<RegionAttributes::Register>) {}
111-
112-
/* our actual flux defs */
113-
114-
flux_rs::defs! {
115-
#[hide]
116-
fn valid_size(x: int) -> bool { 0 <= x && x <= u32::MAX }
117-
118-
fn half_max(r: int) -> bool { r <= u32::MAX / 2 + 1}
119-
120-
fn bv32(x:int) -> bitvec<32> { bv_int_to_bv32(x) }
121-
fn bit(reg: bitvec<32>, power_of_two: bitvec<32>) -> bool { reg & power_of_two != 0}
122-
fn extract(reg: bitvec<32>, mask:int, offset: int) -> bitvec<32> { (reg & bv32(mask)) >> bv32(offset) }
123-
124-
fn least_five_bits(val: bitvec<32>) -> bitvec<32> { val & 0x1F }
125-
126-
// rbar
127-
fn rbar_valid_bit_set(reg: bitvec<32>) -> bool { bit(reg, 0x10) }
128-
fn rbar_region_number(reg: bitvec<32>) -> bitvec<32> { reg & 0xF }
129-
// NOTE: don't shift by 5 because we need the last 5 bits as all 0
130-
fn rbar_region_start(reg: bitvec<32>) -> bitvec<32> { reg & 0xFFFF_FFE0 }
131-
132-
// rasr
133-
fn rasr_global_region_enabled(reg: bitvec<32>) -> bool { bit(reg, 0x1) }
134-
fn exp2(n:bitvec<32>) -> bitvec<32> { (1 << n) }
135-
fn size_from_base2(base2_value:bitvec<32>) -> bitvec<32> { exp2 (base2_value + 1) }
136-
fn rasr_region_size(reg: bitvec<32>) -> bitvec<32> { size_from_base2(extract(reg, 0x0000003e, 1))}
137-
138-
// fn rasr_region_size(reg: bitvec<32>) -> bitvec<32> { 1 << (extract(reg, 0x0000003e, 1) + 1) }
139-
fn rasr_srd(reg: bitvec<32>) -> bitvec<32> { extract(reg, 0x0000_FF00, 8) }
140-
fn rasr_ap(reg: bitvec<32>) -> bitvec<32> { extract(reg, 0x0700_0000, 24) }
141-
fn rasr_xn(reg: bitvec<32>) -> bool { bit(reg, 0x10000000) }
142-
143-
// ctrl
144-
fn enable(reg:bitvec<32>) -> bool { bit(reg, 0x00000001)}
145-
146-
fn enabled_srd_mask(first_subregion: bitvec<32>, last_subregion: bitvec<32>) -> bitvec<32> {
147-
((bv32(1) << ((last_subregion - first_subregion) + 1)) - 1) << first_subregion
148-
}
149-
150-
fn disabled_srd_mask(first_subregion: bitvec<32>, last_subregion: bitvec<32>) -> bitvec<32> {
151-
bv_xor(0xff, enabled_srd_mask(first_subregion, last_subregion))
152-
}
153-
154-
fn perms_match_exactly(rasr: bitvec<32>, perms: mpu::Permissions) -> bool {
155-
let ap = rasr_ap(rasr);
156-
let xn = rasr_xn(rasr);
157-
if perms.r && perms.w && perms.x {
158-
// read write exec
159-
ap == 3 && !xn
160-
} else if perms.r && perms.w && !perms.x {
161-
// read write
162-
ap == 3 && xn
163-
} else if perms.r && !perms.w && perms.x {
164-
// read exec
165-
(ap == 2 || ap == 6 || ap == 7) && !xn
166-
} else if perms.r && !perms.w && !perms.x {
167-
// read only
168-
(ap == 2 || ap == 6 || ap == 7) && xn
169-
} else if !perms.r && !perms.w && perms.x {
170-
(ap == 0 || ap == 1) && !xn
171-
} else {
172-
false
173-
}
174-
}
175-
176-
#[hide]
177-
fn subregions_enabled_bit_set(rasr: bitvec<32>, first_subregion_no: bitvec<32>, last_subregion_no: bitvec<32>) -> bool {
178-
let emask = enabled_srd_mask(first_subregion_no, last_subregion_no);
179-
let srd = rasr_srd(rasr);
180-
((srd & emask) == 0)
181-
}
182-
183-
#[hide]
184-
fn subregions_disabled_bit_set(rasr: bitvec<32>, first_subregion_no: bitvec<32>, last_subregion_no: bitvec<32>) -> bool {
185-
let dmask = disabled_srd_mask(first_subregion_no, last_subregion_no);
186-
let srd = rasr_srd(rasr);
187-
((srd & dmask) == dmask)
188-
}
189-
190-
fn subregions_enabled_exactly(rasr: bitvec<32>, first_subregion_no: bitvec<32>, last_subregion_no: bitvec<32>) -> bool {
191-
subregions_enabled_bit_set(rasr, first_subregion_no, last_subregion_no) &&
192-
subregions_disabled_bit_set(rasr, first_subregion_no, last_subregion_no)
193-
}
194-
195-
#[hide]
196-
fn to_pow2(n: int) -> int {
197-
let bv = bv32(n);
198-
bv_bv32_to_int(bv32(1) << bv)
199-
}
200-
201-
#[hide]
202-
fn pow2(n:int) -> bool {
203-
let bv = bv32(n);
204-
n > 0 && (bv & (bv - 1)) == 0
205-
}
206-
207-
#[hide]
208-
fn aligned(x: int, y: int) -> bool {
209-
x % y == 0
210-
}
211-
212-
#[hide]
213-
fn octet(n: int) -> bool {
214-
n % 8 == 0
215-
}
216-
217-
#[hide]
218-
fn first_subregion_from_logical(rstart: int, rsize: int, astart: int, asize: int) -> int {
219-
let subregion_size = rsize / 8;
220-
(astart - rstart) / subregion_size
221-
}
222-
223-
#[hide]
224-
fn last_subregion_from_logical(rstart: int, rsize: int, astart: int, asize: int) -> int {
225-
let subregion_size = rsize / 8;
226-
(((astart + asize) - rstart) / subregion_size) - 1
227-
}
228-
229-
fn rnum(region: CortexMRegion) -> int { region.region_no}
230-
fn rbar(region: CortexMRegion) -> bitvec<32>{ region.rbar.value }
231-
fn rasr(region: CortexMRegion) -> bitvec<32> { region.rasr.value }
232-
233-
234-
// region specific
235-
fn region_overlaps(region1: CortexMRegion, start: int, end: int) -> bool {
236-
if region1.set {
237-
let fst_region_start = region1.astart;
238-
let fst_region_end = region1.astart + region1.asize;
239-
let snd_region_start = start;
240-
let snd_region_end = end;
241-
fst_region_start < snd_region_end && snd_region_start < fst_region_end
242-
} else {
243-
false
244-
}
245-
}
246-
}
247-
248-
/* bunch of code */
249-
250-
#[flux_rs::trusted(reason = "solver hanging")]
251-
#[flux_rs::sig(fn (start: usize, size: usize) -> usize{r: r >= start && aligned(r, size)} requires size > 0 && start + size <= usize::MAX)]
252-
fn align(start: usize, size: usize) -> usize {
253-
start + size - (start % size)
254-
}
255-
256-
#[flux_rs::reveal(aligned)]
257-
#[flux_rs::sig(fn (start: usize, size: usize) -> bool[aligned(start, size)] requires size > 0)]
258-
fn is_aligned(start: usize, size: usize) -> bool {
259-
start % size == 0
260-
}
261-
262-
// VTOCK-TODO: supplementary proof?
263-
#[flux_rs::trusted(reason = "math support (bitwise arithmetic fact)")]
264-
#[flux_rs::sig(fn(n: u32{n < 32}) -> usize{r: r == to_pow2(n) && r > 0 && r <= u32::MAX})]
265-
fn power_of_two(n: u32) -> usize {
266-
1_usize << n
267-
}
268-
26925
/// MPU Registers for the Cortex-M3, Cortex-M4 and Cortex-M7 families
27026
/// Described in section 4.5 of
27127
/// <http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/DUI0553A_cortex_m4_dgug.pdf>
@@ -293,7 +49,7 @@ struct MpuRegisters {
29349
pub rasr: ReadWrite<u32, RegionAttributes::Register>,
29450
}
29551

296-
register_bitfields![u32,
52+
register_bitfields_u32![u32,
29753
Type [
29854
/// The number of MPU instructions regions supported. Always reads 0.
29955
IREGION OFFSET(16) NUMBITS(8) [],
@@ -346,7 +102,7 @@ register_bitfields![u32,
346102
REGION OFFSET(0) NUMBITS(4) []
347103
],
348104

349-
RegionAttributes [
105+
pub RegionAttributes [
350106
/// Enables instruction fetches/execute permission
351107
XN OFFSET(28) NUMBITS(1) [
352108
Enable = 0,
@@ -386,21 +142,17 @@ const MPU_BASE_ADDRESS: StaticRef<MpuRegisters> =
386142
pub struct MPU<const NUM_REGIONS: usize, const MIN_REGION_SIZE: usize> {
387143
/// MMIO reference to MPU registers.
388144
registers: StaticRef<MpuRegisters>,
389-
/// Monotonically increasing counter for allocated regions, used
390-
/// to assign unique IDs to `CortexMConfig` instances.
391-
config_count: Cell<NonZeroUsize>,
392145
/// Optimization logic. This is used to indicate which application the MPU
393146
/// is currently configured for so that the MPU can skip updating when the
394147
/// kernel returns to the same app.
395-
hardware_is_configured_for: OptionalCell<NonZeroUsize>,
148+
hardware_is_configured_for: OptionalCell<usize>,
396149
}
397150

398151
impl<const NUM_REGIONS: usize, const MIN_REGION_SIZE: usize> MPU<NUM_REGIONS, MIN_REGION_SIZE> {
399152
pub const unsafe fn new() -> Self {
400153
assume(NUM_REGIONS == 8 || NUM_REGIONS == 16);
401154
Self {
402155
registers: MPU_BASE_ADDRESS,
403-
config_count: Cell::new(NonZeroUsize::MIN),
404156
hardware_is_configured_for: OptionalCell::empty(),
405157
}
406158
}
@@ -412,6 +164,14 @@ impl<const NUM_REGIONS: usize, const MIN_REGION_SIZE: usize> MPU<NUM_REGIONS, MI
412164
.ctrl
413165
.write(Control::ENABLE::CLEAR().into_inner());
414166
}
167+
168+
fn is_configured_for(&self, id: usize) -> bool {
169+
if let Some(last_id) = self.hardware_is_configured_for.get() {
170+
last_id == id
171+
} else {
172+
false
173+
}
174+
}
415175
}
416176

417177
/// Per-process struct storing MPU configuration for cortex-m MPUs.
@@ -613,24 +373,6 @@ fn subregion_mask(min_subregion: usize, max_subregion: usize) -> u8 {
613373
}
614374
}
615375

616-
#[flux_rs::trusted]
617-
#[flux_rs::sig(fn (region_start: FluxPtrU8) -> u32{r: least_five_bits(bv32(region_start)) == 0 => bv32(r) << 5 == bv32(region_start)})]
618-
fn region_start_rs32(region_start: FluxPtrU8) -> u32 {
619-
region_start.as_u32() >> 5
620-
}
621-
622-
#[flux_rs::reveal(valid_size)]
623-
#[flux_rs::sig(fn (x: usize, y: usize) -> bool[valid_size(x + y)] requires y <= u32::MAX)]
624-
fn check_valid_size(x: usize, y: usize) -> bool {
625-
x <= u32::MAX as usize - y
626-
}
627-
628-
#[flux_rs::trusted(reason = "math support (valid usize to u32 cast)")]
629-
#[flux_rs::sig(fn ({ usize[@n] | n <= u32::MAX }) -> u32[n])]
630-
fn usize_to_u32(n: usize) -> u32 {
631-
n as u32
632-
}
633-
634376
#[flux_rs::sig(
635377
fn (start: usize, min_size: usize) -> Option<usize{size:
636378
size >= min_size && pow2(size) && aligned(start, size) && octet(size) && half_max(size)
@@ -1338,17 +1080,17 @@ impl CortexMRegion {
13381080
}
13391081
}
13401082

1341-
#[flux_rs::sig(fn (&CortexMRegion[@addr, @attrs, @no, @set, @astart, @asize, @rstart, @rsize, @perms]) -> Option<{l. CortexMLocation[l] | l.astart == astart && l.asize == asize && l.rstart == rstart && l.rsize == rsize}>[set])]
1083+
#[flux_rs::sig(fn (&CortexMRegion[@r]) -> Option<{l. CortexMLocation[l] | l.astart == r.astart && l.asize == r.asize && l.rstart == r.rstart && l.rsize == r.rsize}>[r.set])]
13421084
fn location(&self) -> Option<CortexMLocation> {
13431085
self.location
13441086
}
13451087

1346-
#[flux_rs::sig(fn(&CortexMRegion[@addr, @attrs, @no, @set, @astart, @asize, @rstart, @rsize, @perms]) -> FieldValueU32<RegionBaseAddress::Register>[addr])]
1088+
#[flux_rs::sig(fn(&CortexMRegion[@region]) -> FieldValueU32<RegionBaseAddress::Register>[region.rbar])]
13471089
fn base_address(&self) -> FieldValueU32<RegionBaseAddress::Register> {
13481090
self.base_address
13491091
}
13501092

1351-
#[flux_rs::sig(fn(&CortexMRegion[@addr, @attrs, @no, @set, @astart, @asize, @rstart, @rsize, @perms]) -> FieldValueU32<RegionAttributes::Register>[attrs])]
1093+
#[flux_rs::sig(fn(&CortexMRegion[@region]) -> FieldValueU32<RegionAttributes::Register>[region.rasr])]
13521094
fn attributes(&self) -> FieldValueU32<RegionAttributes::Register> {
13531095
self.attributes
13541096
}
@@ -1419,7 +1161,10 @@ impl<const NUM_REGIONS: usize, const MIN_REGION_SIZE: usize> mpu::MPU
14191161
self.registers.mpu_type.read(Type::DREGION().into_inner()) as usize
14201162
}
14211163

1422-
fn configure_mpu(&self, config: &RArray<CortexMRegion>) {
1164+
fn configure_mpu(&self, config: &RArray<CortexMRegion>, id: usize) {
1165+
if self.is_configured_for(id) {
1166+
return; // fastpath - we are already using this config
1167+
}
14231168
for region in config.iter() {
14241169
self.registers
14251170
.rbar
@@ -1438,5 +1183,6 @@ impl<const NUM_REGIONS: usize, const MIN_REGION_SIZE: usize> mpu::MPU
14381183
self.registers.rasr.write(region.attributes().into_inner());
14391184
}
14401185
}
1186+
self.hardware_is_configured_for.set(id);
14411187
}
14421188
}

0 commit comments

Comments
 (0)