@@ -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
@@ -609,7 +585,7 @@ impl Drop for Vcpu {
609585 #[ cfg( not( test) ) ]
610586 assert ! ( std:: ptr:: eq( _vcpu_ptr, self ) ) ;
611587
612- Self :: TLS_VCPU_PTR . take ( ) ;
588+ TLS_VCPU_PTR . take ( ) ;
613589 }
614590 } )
615591 }
@@ -1015,34 +991,6 @@ pub(crate) mod tests {
1015991 assert ! ( vcpu. kvm_vcpu. peripherals. mmio_bus. is_some( ) ) ;
1016992 }
1017993
1018- #[ test]
1019- fn test_vcpu_tls ( ) {
1020- let ( _, _, mut vcpu) = setup_vcpu ( 0x1000 ) ;
1021-
1022- // Running on the TLS vcpu should fail before we actually initialize it.
1023- unsafe {
1024- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1025- }
1026-
1027- // Initialize vcpu TLS.
1028- vcpu. init_thread_local_data ( ) ;
1029-
1030- // Validate TLS vcpu is the local vcpu by changing the `id` then validating against
1031- // the one in TLS.
1032- vcpu. kvm_vcpu . index = 12 ;
1033- unsafe {
1034- Vcpu :: run_on_thread_local ( |v| assert_eq ! ( v. kvm_vcpu. index, 12 ) ) . unwrap ( ) ;
1035- }
1036-
1037- // Reset vcpu TLS.
1038- Vcpu :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
1039-
1040- // Running on the TLS vcpu after TLS reset should fail.
1041- unsafe {
1042- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1043- }
1044- }
1045-
1046994 #[ test]
1047995 #[ should_panic]
1048996 fn test_tls_double_init ( ) {
0 commit comments