@@ -88,6 +88,8 @@ pub enum CopyKvmFdError {
8888 CreateVcpuError ( #[ from] kvm_ioctls:: Error ) ,
8989}
9090
91+ thread_local ! ( static TLS_VCPU_PTR : VcpuCell = const { Cell :: new( None ) } ) ;
92+
9193/// A wrapper around creating and using a vcpu.
9294#[ derive( Debug ) ]
9395pub struct Vcpu {
@@ -110,61 +112,35 @@ pub struct Vcpu {
110112}
111113
112114impl Vcpu {
113- thread_local ! ( static TLS_VCPU_PTR : VcpuCell = const { Cell :: new( None ) } ) ;
114-
115115 /// Associates `self` with the current thread.
116116 ///
117117 /// It is a prerequisite to successfully run `init_thread_local_data()` before using
118118 /// `run_on_thread_local()` on the current thread.
119119 /// This function will panic if there already is a `Vcpu` present in the TLS.
120120 fn init_thread_local_data ( & mut self ) {
121- Self :: TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
121+ TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
122122 assert ! ( cell. get( ) . is_none( ) ) ;
123123 cell. set ( Some ( self as * mut Vcpu ) ) ;
124124 } )
125125 }
126126
127- /// Runs `func` for the `Vcpu` associated with the current thread.
128- ///
129- /// It requires that `init_thread_local_data()` was run on this thread.
130- ///
131- /// Fails if there is no `Vcpu` associated with the current thread.
132- ///
133- /// # Safety
134- ///
135- /// This is marked unsafe as it allows temporary aliasing through
136- /// dereferencing from pointer an already borrowed `Vcpu`.
137- unsafe fn run_on_thread_local < F > ( func : F ) -> Result < ( ) , VcpuError >
138- where
139- F : FnOnce ( & mut Vcpu ) ,
140- {
141- Self :: TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
142- if let Some ( vcpu_ptr) = cell. get ( ) {
143- // SAFETY: Dereferencing here is safe since `TLS_VCPU_PTR` is populated/non-empty,
144- // and it is being cleared on `Vcpu::drop` so there is no dangling pointer.
145- let vcpu_ref = unsafe { & mut * vcpu_ptr } ;
146- func ( vcpu_ref) ;
147- Ok ( ( ) )
148- } else {
149- Err ( VcpuError :: VcpuTlsNotPresent )
150- }
151- } )
152- }
153-
154127 /// Registers a signal handler which makes use of TLS and kvm immediate exit to
155128 /// kick the vcpu running on the current thread, if there is one.
156129 fn register_kick_signal_handler ( & mut self ) {
157130 self . init_thread_local_data ( ) ;
158131
159132 extern "C" fn handle_signal ( _: c_int , _: * mut siginfo_t , _: * mut c_void ) {
160- // SAFETY: This is safe because it's temporarily aliasing the `Vcpu` object, but we are
161- // only reading `vcpu.fd` which does not change for the lifetime of the `Vcpu`.
162- unsafe {
163- let _ = Vcpu :: run_on_thread_local ( |vcpu| {
133+ TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
134+ if let Some ( vcpu_ptr) = cell. get ( ) {
135+ // SAFETY: Dereferencing here is safe since `TLS_VCPU_PTR` is
136+ // populated/non-empty, and it is being cleared on
137+ // `Vcpu::drop` so there is no dangling pointer.
138+ let vcpu = unsafe { & mut * vcpu_ptr } ;
139+
164140 vcpu. kvm_vcpu . fd . set_kvm_immediate_exit ( 1 ) ;
165141 fence ( Ordering :: Release ) ;
166- } ) ;
167- }
142+ }
143+ } )
168144 }
169145
170146 register_signal_handler ( sigrtmin ( ) + VCPU_RTSIG_OFFSET , handle_signal)
@@ -595,7 +571,7 @@ fn handle_kvm_exit(
595571
596572impl Drop for Vcpu {
597573 fn drop ( & mut self ) {
598- Self :: TLS_VCPU_PTR . with ( |cell| {
574+ TLS_VCPU_PTR . with ( |cell| {
599575 // The reason for not asserting TLS being set here is that
600576 // it can happen that Vcpu::Drop is called on vcpus which never were
601577 // put on their threads. This can happen if some error occurs during Vmm
@@ -611,7 +587,7 @@ impl Drop for Vcpu {
611587
612588 // Have to do this trick because `update` method is
613589 // not stable on Cell.
614- Self :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
590+ TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
615591 }
616592 } )
617593 }
@@ -1017,34 +993,6 @@ pub(crate) mod tests {
1017993 assert ! ( vcpu. kvm_vcpu. peripherals. mmio_bus. is_some( ) ) ;
1018994 }
1019995
1020- #[ test]
1021- fn test_vcpu_tls ( ) {
1022- let ( _, _, mut vcpu) = setup_vcpu ( 0x1000 ) ;
1023-
1024- // Running on the TLS vcpu should fail before we actually initialize it.
1025- unsafe {
1026- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1027- }
1028-
1029- // Initialize vcpu TLS.
1030- vcpu. init_thread_local_data ( ) ;
1031-
1032- // Validate TLS vcpu is the local vcpu by changing the `id` then validating against
1033- // the one in TLS.
1034- vcpu. kvm_vcpu . index = 12 ;
1035- unsafe {
1036- Vcpu :: run_on_thread_local ( |v| assert_eq ! ( v. kvm_vcpu. index, 12 ) ) . unwrap ( ) ;
1037- }
1038-
1039- // Reset vcpu TLS.
1040- Vcpu :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
1041-
1042- // Running on the TLS vcpu after TLS reset should fail.
1043- unsafe {
1044- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1045- }
1046- }
1047-
1048996 #[ test]
1049997 #[ should_panic]
1050998 fn test_tls_double_init ( ) {
0 commit comments