@@ -12,260 +12,16 @@ use core::num::NonZeroUsize;
1212use flux_support:: capability:: MpuEnabledCapability ;
1313use 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;
1618use flux_support:: * ;
1719use kernel:: platform:: mpu:: { self , RegionDescriptor } ;
1820use kernel:: utilities:: cells:: OptionalCell ;
1921use kernel:: utilities:: math;
2022use kernel:: utilities:: registers:: interfaces:: { Readable , Writeable } ;
2123use 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> =
386142pub 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
398151impl < 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