@@ -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,12 +571,12 @@ 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 let vcpu_ptr = cell. get ( ) . unwrap ( ) ;
600576 assert ! ( std:: ptr:: eq( vcpu_ptr, self ) ) ;
601577 // Have to do this trick because `update` method is
602578 // not stable on Cell.
603- Self :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
579+ TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
604580 } )
605581 }
606582}
@@ -999,7 +975,7 @@ pub(crate) mod tests {
999975
1000976 impl Vcpu {
1001977 fn reset_thread_local_data ( & mut self ) {
1002- Self :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
978+ TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
1003979 }
1004980 }
1005981
@@ -1011,34 +987,6 @@ pub(crate) mod tests {
1011987 assert ! ( vcpu. kvm_vcpu. peripherals. mmio_bus. is_some( ) ) ;
1012988 }
1013989
1014- #[ test]
1015- fn test_vcpu_tls ( ) {
1016- let ( _, _, mut vcpu) = setup_vcpu ( 0x1000 ) ;
1017-
1018- // Running on the TLS vcpu should fail before we actually initialize it.
1019- unsafe {
1020- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1021- }
1022-
1023- // Initialize vcpu TLS.
1024- vcpu. init_thread_local_data ( ) ;
1025-
1026- // Validate TLS vcpu is the local vcpu by changing the `id` then validating against
1027- // the one in TLS.
1028- vcpu. kvm_vcpu . index = 12 ;
1029- unsafe {
1030- Vcpu :: run_on_thread_local ( |v| assert_eq ! ( v. kvm_vcpu. index, 12 ) ) . unwrap ( ) ;
1031- }
1032-
1033- // Reset vcpu TLS.
1034- vcpu. reset_thread_local_data ( ) ;
1035-
1036- // Running on the TLS vcpu after TLS reset should fail.
1037- unsafe {
1038- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1039- }
1040- }
1041-
1042990 #[ test]
1043991 #[ should_panic]
1044992 fn test_tls_double_init ( ) {
0 commit comments