1
+ #![ allow( unused) ]
1
2
// Licensed under the Apache License, Version 2.0 or the MIT License.
2
3
// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4
// Copyright Tock Contributors 2022.
29
30
30
31
// )]
31
32
32
- // VTOCK_TODO: better solution for hardware register spooky-action-at-a-distance
33
- /* VTOCK TODOS
34
- 1. Implement configured_for
35
- 2. Implement can_service
36
- */
37
-
38
33
use core:: cell:: Cell ;
39
34
use core:: cmp;
40
35
use core:: fmt;
@@ -46,6 +41,8 @@ use kernel::platform::mpu;
46
41
use kernel:: utilities:: cells:: OptionalCell ;
47
42
use kernel:: utilities:: math;
48
43
44
+ // VTOCK-TODO: NUM_REGIONS currently fixed to 8. Need to also handle 16
45
+
49
46
flux_rs:: defs! {
50
47
fn bv32( x: int) -> bitvec<32 > { bv_int_to_bv32( x) }
51
48
fn bit( reg: bitvec<32 >, power_of_two: int) -> bool { bv_bv32_to_int( bv_and( reg, bv32( power_of_two) ) ) != 0 }
@@ -86,8 +83,43 @@ flux_rs::defs! {
86
83
// }
87
84
// }
88
85
86
+
87
+ fn enabled( mpu: MPU ) -> bool { enable( mpu. ctrl) }
88
+ // VTOCK_TODO: simplify
89
+ fn configured_for( mpu: MPU , config: CortexMConfig ) -> bool {
90
+ map_get( mpu. regions, 0 ) == map_get( config. regions, 0 ) &&
91
+ map_get( mpu. attrs, 0 ) == map_get( config. attrs, 0 ) &&
92
+ map_get( mpu. regions, 1 ) == map_get( config. regions, 1 ) &&
93
+ map_get( mpu. attrs, 1 ) == map_get( config. attrs, 1 ) &&
94
+ map_get( mpu. regions, 2 ) == map_get( config. regions, 2 ) &&
95
+ map_get( mpu. attrs, 2 ) == map_get( config. attrs, 2 ) &&
96
+ map_get( mpu. regions, 3 ) == map_get( config. regions, 3 ) &&
97
+ map_get( mpu. attrs, 3 ) == map_get( config. attrs, 3 ) &&
98
+ map_get( mpu. regions, 4 ) == map_get( config. regions, 4 ) &&
99
+ map_get( mpu. attrs, 4 ) == map_get( config. attrs, 4 ) &&
100
+ map_get( mpu. regions, 5 ) == map_get( config. regions, 5 ) &&
101
+ map_get( mpu. attrs, 5 ) == map_get( config. attrs, 5 ) &&
102
+ map_get( mpu. regions, 6 ) == map_get( config. regions, 6 ) &&
103
+ map_get( mpu. attrs, 6 ) == map_get( config. attrs, 6 ) &&
104
+ map_get( mpu. regions, 7 ) == map_get( config. regions, 7 ) &&
105
+ map_get( mpu. attrs, 7 ) == map_get( config. attrs, 7 )
106
+ }
107
+ // fn user_can_access(mpu: Mpu, addr: int, sz: int, perms: mpu::Permissions) -> {
108
+ // }
109
+ // fn contains(raddr: int, rsize: int, addr: int, size: int) -> bool {
110
+ // ((addr >= raddr) && (addr + size < raddr + rsize))
111
+ // }
112
+
113
+
89
114
}
90
115
116
+ // VTOCK_TODO: better solution for hardware register spooky-action-at-a-distance
117
+ /* VTOCK TODOS
118
+ 1. enabled
119
+ 2. Implement configured_for
120
+ 3. Implement can_service
121
+ */
122
+
91
123
// VTOCK-TODO: supplementary proof?
92
124
#[ flux_rs:: sig( fn ( n: u32 { n < 32 } ) -> usize { r: r > 0 } ) ]
93
125
#[ flux_rs:: trusted]
@@ -296,6 +328,8 @@ impl<const MIN_REGION_SIZE: usize> MPU<MIN_REGION_SIZE> {
296
328
297
329
const NUM_REGIONS : usize = 8 ;
298
330
331
+ #[ flux_rs:: opaque]
332
+ #[ flux_rs:: refined_by( dirty: bool , regions: Map <int, int>, attrs: Map <int, int>) ]
299
333
pub struct CortexMConfig {
300
334
/// Unique ID for this configuration, assigned from a
301
335
/// monotonically increasing counter in the MPU struct.
@@ -316,7 +350,7 @@ const APP_MEMORY_REGION_MAX_NUM: usize = 1;
316
350
impl fmt:: Display for CortexMConfig {
317
351
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
318
352
write ! ( f, "\r \n Cortex-M MPU" ) ?;
319
- for ( i, region) in self . regions . iter ( ) . enumerate ( ) {
353
+ for ( i, region) in self . regions_iter ( ) . enumerate ( ) {
320
354
if let Some ( location) = region. location ( ) {
321
355
let access_bits = region. attributes ( ) . read ( RegionAttributes :: AP ( ) ) ;
322
356
let start = location. 0 . as_usize ( ) ;
@@ -357,10 +391,44 @@ impl fmt::Display for CortexMConfig {
357
391
}
358
392
359
393
impl CortexMConfig {
394
+ #[ flux_rs:: trusted]
395
+ fn id ( & self ) -> NonZeroUsize {
396
+ self . id
397
+ }
398
+
399
+ #[ flux_rs:: trusted]
400
+ fn is_dirty ( & self ) -> bool {
401
+ self . is_dirty . get ( )
402
+ }
403
+
404
+ #[ flux_rs:: trusted]
405
+ fn set_dirty ( & self , b : bool ) {
406
+ self . is_dirty . set ( b)
407
+ }
408
+
409
+ #[ flux_rs:: trusted]
410
+ // #[flux_rs::sig(fn(self: &Self, idx: usize, region: CortexMRegion))]
411
+ // map_get
412
+ fn region_get ( & self , idx : usize ) -> & CortexMRegion {
413
+ & self . regions [ idx]
414
+ }
415
+
416
+ #[ flux_rs:: trusted]
417
+ // map_set
418
+ // #[flux_rs::sig(fn(self: &strg Self[@dirty, @regions, @attrs], idx: usize, region: CortexMRegion) ensures self: Self[dirty, map_set(regions, idx, region.addr), map_set(attrs, idx, region.attrs)])]
419
+ fn region_set ( & mut self , idx : usize , region : CortexMRegion ) {
420
+ self . regions [ idx] = region
421
+ }
422
+
423
+ #[ flux_rs:: trusted]
424
+ fn regions_iter ( & self ) -> core:: slice:: Iter < ' _ , CortexMRegion > {
425
+ self . regions . iter ( )
426
+ }
427
+
360
428
#[ flux_rs:: trusted] // need spec for enumerate for this to work
361
429
#[ flux_rs:: sig( fn ( & CortexMConfig ) -> Option <usize { r: r > 1 && r < 8 } >) ]
362
430
fn unused_region_number ( & self ) -> Option < usize > {
363
- for ( number, region) in self . regions . iter ( ) . enumerate ( ) {
431
+ for ( number, region) in self . regions_iter ( ) . enumerate ( ) {
364
432
if number <= APP_MEMORY_REGION_MAX_NUM {
365
433
continue ;
366
434
}
@@ -543,6 +611,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
543
611
self . registers . mpu_type . read ( Type :: DREGION ( ) ) as usize
544
612
}
545
613
614
+ #[ flux_rs:: trusted]
546
615
fn new_config ( & self ) -> Option < Self :: MpuConfig > {
547
616
let id = self . config_count . get ( ) ;
548
617
self . config_count . set ( id. checked_add ( 1 ) ?) ;
@@ -551,7 +620,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
551
620
// write the properly-indexed `CortexMRegion`s:
552
621
let mut ret = CortexMConfig {
553
622
id,
554
- regions : [ CortexMRegion :: empty ( 0 ) ; NUM_REGIONS ] ,
623
+ regions : [ CortexMRegion :: empty ( 0 ) ; 8 ] ,
555
624
is_dirty : Cell :: new ( true ) ,
556
625
} ;
557
626
@@ -561,16 +630,16 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
561
630
}
562
631
563
632
fn reset_config ( & self , config : & mut Self :: MpuConfig ) {
564
- config. regions [ 0 ] = CortexMRegion :: empty ( 0 ) ;
565
- config. regions [ 1 ] = CortexMRegion :: empty ( 1 ) ;
566
- config. regions [ 2 ] = CortexMRegion :: empty ( 2 ) ;
567
- config. regions [ 3 ] = CortexMRegion :: empty ( 3 ) ;
568
- config. regions [ 4 ] = CortexMRegion :: empty ( 4 ) ;
569
- config. regions [ 5 ] = CortexMRegion :: empty ( 5 ) ;
570
- config. regions [ 6 ] = CortexMRegion :: empty ( 6 ) ;
571
- config. regions [ 7 ] = CortexMRegion :: empty ( 7 ) ;
572
-
573
- config. is_dirty . set ( true ) ;
633
+ config. region_set ( 0 , CortexMRegion :: empty ( 0 ) ) ;
634
+ config. region_set ( 1 , CortexMRegion :: empty ( 1 ) ) ;
635
+ config. region_set ( 2 , CortexMRegion :: empty ( 2 ) ) ;
636
+ config. region_set ( 3 , CortexMRegion :: empty ( 3 ) ) ;
637
+ config. region_set ( 4 , CortexMRegion :: empty ( 4 ) ) ;
638
+ config. region_set ( 5 , CortexMRegion :: empty ( 5 ) ) ;
639
+ config. region_set ( 6 , CortexMRegion :: empty ( 6 ) ) ;
640
+ config. region_set ( 7 , CortexMRegion :: empty ( 7 ) ) ;
641
+
642
+ config. set_dirty ( true ) ;
574
643
}
575
644
576
645
fn allocate_region (
@@ -584,7 +653,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
584
653
assume ( min_region_size < 2147483648 ) ;
585
654
586
655
// Check that no previously allocated regions overlap the unallocated memory.
587
- for region in config. regions . iter ( ) {
656
+ for region in config. regions_iter ( ) {
588
657
if region. overlaps ( unallocated_memory_start, unallocated_memory_size) {
589
658
return None ;
590
659
}
@@ -699,8 +768,8 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
699
768
permissions,
700
769
) ;
701
770
702
- config. regions [ region_num] = region;
703
- config. is_dirty . set ( true ) ;
771
+ config. region_set ( region_num, region) ;
772
+ config. set_dirty ( true ) ;
704
773
705
774
Some ( mpu:: Region :: new ( start. as_fluxptr ( ) , size) )
706
775
}
@@ -711,8 +780,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
711
780
config : & mut Self :: MpuConfig ,
712
781
) -> Result < ( ) , ( ) > {
713
782
let ( idx, _r) = config
714
- . regions
715
- . iter ( )
783
+ . regions_iter ( )
716
784
. enumerate ( )
717
785
. find ( |( _idx, r) | * * r == region)
718
786
. ok_or ( ( ) ) ?;
@@ -722,8 +790,8 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
722
790
}
723
791
assume ( idx < 8 ) ; // need spec for find
724
792
725
- config. regions [ idx] = CortexMRegion :: empty ( idx) ;
726
- config. is_dirty . set ( true ) ;
793
+ config. region_set ( idx, CortexMRegion :: empty ( idx) ) ;
794
+ config. set_dirty ( true ) ;
727
795
728
796
Ok ( ( ) )
729
797
}
@@ -743,7 +811,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
743
811
) -> Option < ( FluxPtrU8 , usize ) > {
744
812
// Check that no previously allocated regions overlap the unallocated
745
813
// memory.
746
- for region in config. regions . iter ( ) {
814
+ for region in config. regions_iter ( ) {
747
815
if region. overlaps ( unallocated_memory_start, unallocated_memory_size) {
748
816
return None ;
749
817
}
@@ -861,9 +929,9 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
861
929
)
862
930
} ;
863
931
864
- config. regions [ 0 ] = region0;
865
- config. regions [ 1 ] = region1;
866
- config. is_dirty . set ( true ) ;
932
+ config. region_set ( 0 , region0) ;
933
+ config. region_set ( 1 , region1) ;
934
+ config. set_dirty ( true ) ;
867
935
868
936
Some ( ( region_start. as_fluxptr ( ) , memory_size_po2) )
869
937
}
@@ -877,7 +945,7 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
877
945
) -> Result < ( ) , ( ) > {
878
946
// Get first region, or error if the process tried to update app memory
879
947
// MPU region before it was created.
880
- let ( region_start_ptr, region_size) = config. regions [ 0 ] . location ( ) . ok_or ( ( ) ) ?;
948
+ let ( region_start_ptr, region_size) = config. region_get ( 0 ) . location ( ) . ok_or ( ( ) ) ?;
881
949
let region_start = region_start_ptr. as_usize ( ) ;
882
950
883
951
let app_memory_break = app_memory_break. as_usize ( ) ;
@@ -938,9 +1006,9 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
938
1006
)
939
1007
} ;
940
1008
941
- config. regions [ 0 ] = region0;
942
- config. regions [ 1 ] = region1;
943
- config. is_dirty . set ( true ) ;
1009
+ config. region_set ( 0 , region0) ;
1010
+ config. region_set ( 1 , region1) ;
1011
+ config. set_dirty ( true ) ;
944
1012
945
1013
Ok ( ( ) )
946
1014
}
@@ -949,13 +1017,13 @@ impl<const MIN_REGION_SIZE: usize> mpu::MPU for MPU<MIN_REGION_SIZE> {
949
1017
fn configure_mpu ( & mut self , config : & Self :: MpuConfig ) {
950
1018
// If the hardware is already configured for this app and the app's MPU
951
1019
// configuration has not changed, then skip the hardware update.
952
- if !self . hardware_is_configured_for . contains ( & config. id ) || config. is_dirty . get ( ) {
1020
+ if !self . hardware_is_configured_for . contains ( & config. id ( ) ) || config. is_dirty ( ) {
953
1021
// Set MPU regions
954
- for region in config. regions . iter ( ) {
1022
+ for region in config. regions_iter ( ) {
955
1023
self . commit_region ( region) ;
956
1024
}
957
- self . hardware_is_configured_for . set ( config. id ) ;
958
- config. is_dirty . set ( false ) ;
1025
+ self . hardware_is_configured_for . set ( config. id ( ) ) ;
1026
+ config. set_dirty ( false ) ;
959
1027
}
960
1028
}
961
1029
}
0 commit comments