@@ -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)
@@ -599,12 +575,12 @@ fn handle_kvm_exit(
599
575
#[ cfg( not( test) ) ]
600
576
impl Drop for Vcpu {
601
577
fn drop ( & mut self ) {
602
- Self :: TLS_VCPU_PTR . with ( |cell| {
578
+ TLS_VCPU_PTR . with ( |cell| {
603
579
let vcpu_ptr = cell. get ( ) . unwrap ( ) ;
604
580
assert ! ( std:: ptr:: eq( vcpu_ptr, self ) ) ;
605
581
// Have to do this trick because `update` method is
606
582
// not stable on Cell.
607
- Self :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
583
+ TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
608
584
} )
609
585
}
610
586
}
@@ -1009,34 +985,6 @@ pub(crate) mod tests {
1009
985
assert ! ( vcpu. kvm_vcpu. peripherals. mmio_bus. is_some( ) ) ;
1010
986
}
1011
987
1012
- #[ test]
1013
- fn test_vcpu_tls ( ) {
1014
- let ( _, _, mut vcpu) = setup_vcpu ( 0x1000 ) ;
1015
-
1016
- // Running on the TLS vcpu should fail before we actually initialize it.
1017
- unsafe {
1018
- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1019
- }
1020
-
1021
- // Initialize vcpu TLS.
1022
- vcpu. init_thread_local_data ( ) ;
1023
-
1024
- // Validate TLS vcpu is the local vcpu by changing the `id` then validating against
1025
- // the one in TLS.
1026
- vcpu. kvm_vcpu . index = 12 ;
1027
- unsafe {
1028
- Vcpu :: run_on_thread_local ( |v| assert_eq ! ( v. kvm_vcpu. index, 12 ) ) . unwrap ( ) ;
1029
- }
1030
-
1031
- // Reset vcpu TLS.
1032
- Vcpu :: TLS_VCPU_PTR . with ( |cell| cell. take ( ) ) ;
1033
-
1034
- // Running on the TLS vcpu after TLS reset should fail.
1035
- unsafe {
1036
- Vcpu :: run_on_thread_local ( |_| ( ) ) . unwrap_err ( ) ;
1037
- }
1038
- }
1039
-
1040
988
#[ test]
1041
989
#[ should_panic]
1042
990
fn test_tls_double_init ( ) {
0 commit comments