@@ -10,6 +10,11 @@ use super::messages::{Confirmation, MemEvents, StartFfiInfo, TraceRequest};
1010use  super :: parent:: { ChildListener ,  sv_loop} ; 
1111use  crate :: alloc:: isolated_alloc:: IsolatedAlloc ; 
1212
13+ /// A handle to the single, shared supervisor process across all `MiriMachine`s. 
14+ /// Since it would be very difficult to trace multiple FFI calls in parallel, we 
15+ /// need to ensure that either (a) only one `MiriMachine` is performing an FFI call 
16+ /// at any given time, or (b) there are distinct supervisor and child processes for 
17+ /// each machine. The former was chosen here. 
1318static  SUPERVISOR :  std:: sync:: Mutex < Option < Supervisor > >  = std:: sync:: Mutex :: new ( None ) ; 
1419
1520/// The main means of communication between the child and parent process, 
@@ -24,6 +29,12 @@ pub struct Supervisor {
2429event_rx :  ipc:: IpcReceiver < MemEvents > , 
2530} 
2631
32+ pub  struct  SvFfiGuard < ' a >  { 
33+     alloc :  & ' a  Rc < RefCell < IsolatedAlloc > > , 
34+     sv_guard :  std:: sync:: MutexGuard < ' static ,  Option < Supervisor > > , 
35+     cb_stack :  Option < * mut  [ u8 ;  CALLBACK_STACK_SIZE ] > , 
36+ } 
37+ 
2738/// Marker representing that an error occurred during creation of the supervisor. 
2839#[ derive( Debug ) ]  
2940pub  struct  SvInitError ; 
@@ -46,20 +57,24 @@ impl Supervisor {
4657/// after the desired call has concluded. 
4758pub  unsafe  fn  start_ffi ( 
4859        alloc :  & Rc < RefCell < IsolatedAlloc > > , 
49-     )  -> ( std :: sync :: MutexGuard < ' static ,   Option < Supervisor > > ,   Option < * mut   [ u8 ;   CALLBACK_STACK_SIZE ] > ) 
60+     )  -> SvFfiGuard < ' _ > 
5061    { 
5162        let  mut  sv_guard = SUPERVISOR . lock ( ) . unwrap ( ) ; 
5263        // If the supervisor is not initialised for whatever reason, fast-return. 
5364        // This might be desired behaviour, as even on platforms where ptracing 
5465        // is not implemented it enables us to enforce that only one FFI call 
5566        // happens at a time. 
5667        let  Some ( sv)  = sv_guard. as_mut ( )  else  { 
57-             return  ( sv_guard,  None ) ; 
68+             return  SvFfiGuard  { 
69+                 alloc, 
70+                 sv_guard, 
71+                 cb_stack :  None , 
72+             } ; 
5873        } ; 
5974
6075        // Get pointers to all the pages the supervisor must allow accesses in 
6176        // and prepare the callback stack. 
62-         let  page_ptrs = alloc. borrow ( ) . pages ( ) ; 
77+         let  page_ptrs = alloc. borrow ( ) . pages ( ) . collect ( ) ; 
6378        let  raw_stack_ptr:  * mut  [ u8 ;  CALLBACK_STACK_SIZE ]  =
6479            Box :: leak ( Box :: new ( [ 0u8 ;  CALLBACK_STACK_SIZE ] ) ) . as_mut_ptr ( ) . cast ( ) ; 
6580        let  stack_ptr = raw_stack_ptr. expose_provenance ( ) ; 
@@ -86,7 +101,11 @@ impl Supervisor {
86101        // modifications to our memory - simply waiting on the recv() doesn't 
87102        // count. 
88103        signal:: raise ( signal:: SIGSTOP ) . unwrap ( ) ; 
89-         ( sv_guard,  Some ( raw_stack_ptr) ) 
104+         SvFfiGuard  { 
105+             alloc, 
106+             sv_guard, 
107+             cb_stack :  Some ( raw_stack_ptr) , 
108+         } 
90109    } 
91110
92111    /// Undoes FFI-related preparations, allowing Miri to continue as normal, then 
@@ -98,10 +117,12 @@ impl Supervisor {
98117/// received by a prior call to `start_ffi`, and the allocator must be the 
99118/// one passed to it also. 
100119pub  unsafe  fn  end_ffi ( 
101-         alloc :  & Rc < RefCell < IsolatedAlloc > > , 
102-         mut  sv_guard :  std:: sync:: MutexGuard < ' static ,  Option < Supervisor > > , 
103-         raw_stack_ptr :  Option < * mut  [ u8 ;  CALLBACK_STACK_SIZE ] > , 
120+         guard :  SvFfiGuard < ' _ > , 
104121    )  -> Option < MemEvents >  { 
122+         let  alloc = guard. alloc ; 
123+         let  mut  sv_guard = guard. sv_guard ; 
124+         let  cb_stack = guard. cb_stack ; 
125+ 
105126        // We can't use IPC channels here to signal that FFI mode has ended, 
106127        // since they might allocate memory which could get us stuck in a SIGTRAP 
107128        // with no easy way out! While this could be worked around, it is much 
@@ -121,7 +142,7 @@ impl Supervisor {
121142        // SAFETY: Caller upholds that this pointer was allocated as a box with 
122143        // this type. 
123144        unsafe  { 
124-             drop ( Box :: from_raw ( raw_stack_ptr . unwrap ( ) ) ) ; 
145+             drop ( Box :: from_raw ( cb_stack . unwrap ( ) ) ) ; 
125146        } 
126147        // On the off-chance something really weird happens, don't block forever. 
127148        sv. event_rx 
@@ -130,7 +151,7 @@ impl Supervisor {
130151                match  e { 
131152                    ipc:: TryRecvError :: IpcError ( _)  => ( ) , 
132153                    ipc:: TryRecvError :: Empty  =>
133-                         eprintln ! ( "Waiting for accesses from supervisor timed out!" ) , 
154+                         panic ! ( "Waiting for accesses from supervisor timed out!" ) , 
134155                } 
135156            } ) 
136157            . ok ( ) 
@@ -141,6 +162,10 @@ impl Supervisor {
141162/// supervisor process could not be created successfully; else, the caller 
142163/// is now the child process and can communicate via `start_ffi`/`end_ffi`, 
143164/// receiving back events through `get_events`. 
165+ ///  
166+ /// When forking to initialise the supervisor, the child raises a `SIGSTOP`; if 
167+ /// the parent successfully ptraces the child, it will allow it to resume. Else, 
168+ /// the child will be killed by the parent. 
144169/// 
145170/// # Safety 
146171/// The invariants for `fork()` must be upheld by the caller, namely either: 
@@ -151,11 +176,6 @@ pub unsafe fn init_sv() -> Result<(), SvInitError> {
151176    // FIXME: Much of this could be reimplemented via the mitosis crate if we upstream the 
152177    // relevant missing bits. 
153178
154-     // Not on a properly supported architecture! 
155-     if  cfg ! ( not( any( target_arch = "x86" ,  target_arch = "x86_64" ,  target_arch = "aarch64" ) ) )  { 
156-         return  Err ( SvInitError ) ; 
157-     } 
158- 
159179    // On Linux, this will check whether ptrace is fully disabled by the Yama module. 
160180    // If Yama isn't running or we're not on Linux, we'll still error later, but 
161181    // this saves a very expensive fork call. 
0 commit comments