@@ -88,6 +88,8 @@ pub enum CopyKvmFdError {
88
88
CreateVcpuError ( #[ from] kvm_ioctls:: Error ) ,
89
89
}
90
90
91
+ thread_local ! ( static TLS_VCPU_PTR : VcpuCell = const { Cell :: new( None ) } ) ;
92
+
91
93
/// A wrapper around creating and using a vcpu.
92
94
#[ derive( Debug ) ]
93
95
pub struct Vcpu {
@@ -110,61 +112,35 @@ pub struct Vcpu {
110
112
}
111
113
112
114
impl Vcpu {
113
- thread_local ! ( static TLS_VCPU_PTR : VcpuCell = const { Cell :: new( None ) } ) ;
114
-
115
115
/// Associates `self` with the current thread.
116
116
///
117
117
/// It is a prerequisite to successfully run `init_thread_local_data()` before using
118
118
/// `run_on_thread_local()` on the current thread.
119
119
/// This function will panic if there already is a `Vcpu` present in the TLS.
120
120
fn init_thread_local_data ( & mut self ) {
121
- Self :: TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
121
+ TLS_VCPU_PTR . with ( |cell : & VcpuCell | {
122
122
assert ! ( cell. get( ) . is_none( ) ) ;
123
123
cell. set ( Some ( self as * mut Vcpu ) ) ;
124
124
} )
125
125
}
126
126
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
-
154
127
/// Registers a signal handler which makes use of TLS and kvm immediate exit to
155
128
/// kick the vcpu running on the current thread, if there is one.
156
129
fn register_kick_signal_handler ( & mut self ) {
157
130
self . init_thread_local_data ( ) ;
158
131
159
132
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
+
164
140
vcpu. kvm_vcpu . fd . set_kvm_immediate_exit ( 1 ) ;
165
141
fence ( Ordering :: Release ) ;
166
- } ) ;
167
- }
142
+ }
143
+ } )
168
144
}
169
145
170
146
register_signal_handler ( sigrtmin ( ) + VCPU_RTSIG_OFFSET , handle_signal)
@@ -595,7 +571,7 @@ fn handle_kvm_exit(
595
571
596
572
impl Drop for Vcpu {
597
573
fn drop ( & mut self ) {
598
- Self :: TLS_VCPU_PTR . with ( |cell| {
574
+ TLS_VCPU_PTR . with ( |cell| {
599
575
// The reason for not asserting TLS being set here is that
600
576
// it can happen that Vcpu::Drop is called on vcpus which never were
601
577
// put on their threads. This can happen if some error occurs during Vmm
@@ -611,7 +587,7 @@ impl Drop for Vcpu {
611
587
612
588
// Have to do this trick because `update` method is
613
589
// not stable on Cell.
614
- Self :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
590
+ TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
615
591
}
616
592
} )
617
593
}
@@ -1017,34 +993,6 @@ pub(crate) mod tests {
1017
993
assert ! ( vcpu. kvm_vcpu. peripherals. mmio_bus. is_some( ) ) ;
1018
994
}
1019
995
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
-
1048
996
#[ test]
1049
997
#[ should_panic]
1050
998
fn test_tls_double_init ( ) {
0 commit comments