@@ -9,8 +9,8 @@ use std::collections::{HashMap, HashSet};
9
9
use std:: fmt:: Debug ;
10
10
11
11
use kvm_bindings:: {
12
- kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_regs , kvm_sregs , kvm_vcpu_events , kvm_xcrs ,
13
- kvm_xsave, CpuId , Msrs , KVM_MAX_CPUID_ENTRIES , KVM_MAX_MSR_ENTRIES ,
12
+ kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_msr_entry , kvm_regs , kvm_sregs ,
13
+ kvm_vcpu_events , kvm_xcrs , kvm_xsave, CpuId , Msrs , KVM_MAX_CPUID_ENTRIES , KVM_MAX_MSR_ENTRIES ,
14
14
} ;
15
15
use kvm_ioctls:: { VcpuExit , VcpuFd } ;
16
16
use log:: { error, warn} ;
@@ -165,22 +165,17 @@ impl KvmVcpu {
165
165
} )
166
166
}
167
167
168
- /// Configures a x86_64 specific vcpu for booting Linux and should be called once per vcpu .
169
- ///
168
+ /// General configuration - common for both boot and hotplugged CPUs .
169
+ /// Normalizes and sets the CPUID in KVM and creates KVM MSRs
170
170
/// # Arguments
171
- ///
172
- /// * `guest_mem` - The guest memory used by this microvm.
173
- /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts.
174
- /// * `vcpu_config` - The vCPU configuration.
175
- /// * `cpuid` - The capabilities exposed by this vCPU.
176
- pub fn configure (
171
+ /// * vcpu_config - The configuration for the vCPUs.
172
+ /// * msrs - The MSRs currently present.
173
+ fn configure_common (
177
174
& mut self ,
178
- guest_mem : & GuestMemoryMmap ,
179
- kernel_start_addr : GuestAddress ,
180
175
vcpu_config : & VcpuConfig ,
181
- ) -> Result < ( ) , KvmVcpuConfigureError > {
176
+ msrs : HashMap < u32 , u64 > ,
177
+ ) -> Result < ( Vec < kvm_msr_entry > , CpuId ) , KvmVcpuConfigureError > {
182
178
let mut cpuid = vcpu_config. cpu_config . cpuid . clone ( ) ;
183
-
184
179
// Apply machine specific changes to CPUID.
185
180
cpuid. normalize (
186
181
// The index of the current logical CPU in the range [0..cpu_count].
@@ -199,6 +194,35 @@ impl KvmVcpu {
199
194
. set_cpuid2 ( & kvm_cpuid)
200
195
. map_err ( KvmVcpuConfigureError :: SetCpuid ) ?;
201
196
197
+ // // Clone MSR entries that are modified by CPU template from `VcpuConfig`.
198
+
199
+ let kvm_msrs = msrs
200
+ . clone ( )
201
+ . into_iter ( )
202
+ . map ( |entry| kvm_bindings:: kvm_msr_entry {
203
+ index : entry. 0 ,
204
+ data : entry. 1 ,
205
+ ..Default :: default ( )
206
+ } )
207
+ . collect :: < Vec < _ > > ( ) ;
208
+
209
+ Ok ( ( kvm_msrs, kvm_cpuid) )
210
+ }
211
+
212
+ /// Configures a x86_64 specific vcpu for booting Linux and should be called once per vcpu.
213
+ ///
214
+ /// # Arguments
215
+ ///
216
+ /// * `guest_mem` - The guest memory used by this microvm.
217
+ /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts.
218
+ /// * `vcpu_config` - The vCPU configuration.
219
+ /// * `cpuid` - The capabilities exposed by this vCPU.
220
+ pub fn configure (
221
+ & mut self ,
222
+ guest_mem : & GuestMemoryMmap ,
223
+ kernel_start_addr : GuestAddress ,
224
+ vcpu_config : & VcpuConfig ,
225
+ ) -> Result < ( ) , KvmVcpuConfigureError > {
202
226
// Clone MSR entries that are modified by CPU template from `VcpuConfig`.
203
227
let mut msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
204
228
self . msrs_to_save . extend ( msrs. keys ( ) ) ;
@@ -208,6 +232,8 @@ impl KvmVcpu {
208
232
msrs. insert ( entry. index , entry. data ) ;
209
233
} ) ;
210
234
235
+ let ( kvm_msrs, kvm_cpuid) = self . configure_common ( vcpu_config, msrs) ?;
236
+
211
237
// TODO - Add/amend MSRs for vCPUs based on cpu_config
212
238
// By this point the Guest CPUID is established. Some CPU features require MSRs
213
239
// to configure and interact with those features. If a MSR is writable from
@@ -226,15 +252,6 @@ impl KvmVcpu {
226
252
// save is `architectural MSRs` + `MSRs inferred through CPUID` + `other
227
253
// MSRs defined by the template`
228
254
229
- let kvm_msrs = msrs
230
- . into_iter ( )
231
- . map ( |entry| kvm_bindings:: kvm_msr_entry {
232
- index : entry. 0 ,
233
- data : entry. 1 ,
234
- ..Default :: default ( )
235
- } )
236
- . collect :: < Vec < _ > > ( ) ;
237
-
238
255
crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
239
256
crate :: arch:: x86_64:: regs:: setup_regs ( & self . fd , kernel_start_addr. raw_value ( ) ) ?;
240
257
crate :: arch:: x86_64:: regs:: setup_fpu ( & self . fd ) ?;
@@ -244,6 +261,25 @@ impl KvmVcpu {
244
261
Ok ( ( ) )
245
262
}
246
263
264
+ /// Configures an x86_64 cpu that has been hotplugged post-boot. Called once per hotplugged
265
+ /// vcpu.
266
+ ///
267
+ /// # Arguments
268
+ ///
269
+ /// * `vcpu_config` - The config to be applied to the vCPU, defined at boot time.
270
+ pub fn hotplug_configure (
271
+ & mut self ,
272
+ vcpu_config : & VcpuConfig ,
273
+ ) -> Result < ( ) , KvmVcpuConfigureError > {
274
+ let msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
275
+ let ( kvm_msrs, _) = self . configure_common ( vcpu_config, msrs) ?;
276
+
277
+ crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
278
+ crate :: arch:: x86_64:: interrupts:: set_lint ( & self . fd ) ?;
279
+
280
+ Ok ( ( ) )
281
+ }
282
+
247
283
/// Sets a Port Mapped IO bus for this vcpu.
248
284
pub fn set_pio_bus ( & mut self , pio_bus : crate :: devices:: Bus ) {
249
285
self . peripherals . pio_bus = Some ( pio_bus) ;
0 commit comments