@@ -9,8 +9,8 @@ use std::collections::BTreeMap;
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} ;
@@ -178,22 +178,17 @@ impl KvmVcpu {
178
178
} )
179
179
}
180
180
181
- /// Configures a x86_64 specific vcpu for booting Linux and should be called once per vcpu .
182
- ///
181
+ /// General configuration - common for both boot and hotplugged CPUs .
182
+ /// Normalizes and sets the CPUID in KVM and creates KVM MSRs
183
183
/// # Arguments
184
- ///
185
- /// * `guest_mem` - The guest memory used by this microvm.
186
- /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts.
187
- /// * `vcpu_config` - The vCPU configuration.
188
- /// * `cpuid` - The capabilities exposed by this vCPU.
189
- pub fn configure (
184
+ /// * vcpu_config - The configuration for the vCPUs.
185
+ /// * msrs - The MSRs currently present.
186
+ fn configure_common (
190
187
& mut self ,
191
- guest_mem : & GuestMemoryMmap ,
192
- kernel_start_addr : GuestAddress ,
193
188
vcpu_config : & VcpuConfig ,
194
- ) -> Result < ( ) , KvmVcpuConfigureError > {
189
+ msrs : std:: collections:: BTreeMap < u32 , u64 > ,
190
+ ) -> Result < ( Vec < kvm_msr_entry > , CpuId ) , KvmVcpuConfigureError > {
195
191
let mut cpuid = vcpu_config. cpu_config . cpuid . clone ( ) ;
196
-
197
192
// Apply machine specific changes to CPUID.
198
193
cpuid. normalize (
199
194
// The index of the current logical CPU in the range [0..cpu_count].
@@ -212,6 +207,35 @@ impl KvmVcpu {
212
207
. set_cpuid2 ( & kvm_cpuid)
213
208
. map_err ( KvmVcpuConfigureError :: SetCpuid ) ?;
214
209
210
+ // // Clone MSR entries that are modified by CPU template from `VcpuConfig`.
211
+
212
+ let kvm_msrs = msrs
213
+ . clone ( )
214
+ . into_iter ( )
215
+ . map ( |entry| kvm_bindings:: kvm_msr_entry {
216
+ index : entry. 0 ,
217
+ data : entry. 1 ,
218
+ ..Default :: default ( )
219
+ } )
220
+ . collect :: < Vec < _ > > ( ) ;
221
+
222
+ Ok ( ( kvm_msrs, kvm_cpuid) )
223
+ }
224
+
225
+ /// Configures a x86_64 specific vcpu for booting Linux and should be called once per vcpu.
226
+ ///
227
+ /// # Arguments
228
+ ///
229
+ /// * `guest_mem` - The guest memory used by this microvm.
230
+ /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts.
231
+ /// * `vcpu_config` - The vCPU configuration.
232
+ /// * `cpuid` - The capabilities exposed by this vCPU.
233
+ pub fn configure (
234
+ & mut self ,
235
+ guest_mem : & GuestMemoryMmap ,
236
+ kernel_start_addr : GuestAddress ,
237
+ vcpu_config : & VcpuConfig ,
238
+ ) -> Result < ( ) , KvmVcpuConfigureError > {
215
239
// Clone MSR entries that are modified by CPU template from `VcpuConfig`.
216
240
let mut msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
217
241
self . msrs_to_save . extend ( msrs. keys ( ) ) ;
@@ -221,6 +245,8 @@ impl KvmVcpu {
221
245
msrs. insert ( entry. index , entry. data ) ;
222
246
} ) ;
223
247
248
+ let ( kvm_msrs, kvm_cpuid) = self . configure_common ( vcpu_config, msrs) ?;
249
+
224
250
// TODO - Add/amend MSRs for vCPUs based on cpu_config
225
251
// By this point the Guest CPUID is established. Some CPU features require MSRs
226
252
// to configure and interact with those features. If a MSR is writable from
@@ -239,15 +265,6 @@ impl KvmVcpu {
239
265
// save is `architectural MSRs` + `MSRs inferred through CPUID` + `other
240
266
// MSRs defined by the template`
241
267
242
- let kvm_msrs = msrs
243
- . into_iter ( )
244
- . map ( |entry| kvm_bindings:: kvm_msr_entry {
245
- index : entry. 0 ,
246
- data : entry. 1 ,
247
- ..Default :: default ( )
248
- } )
249
- . collect :: < Vec < _ > > ( ) ;
250
-
251
268
crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
252
269
crate :: arch:: x86_64:: regs:: setup_regs ( & self . fd , kernel_start_addr. raw_value ( ) ) ?;
253
270
crate :: arch:: x86_64:: regs:: setup_fpu ( & self . fd ) ?;
@@ -257,6 +274,25 @@ impl KvmVcpu {
257
274
Ok ( ( ) )
258
275
}
259
276
277
+ /// Configures an x86_64 cpu that has been hotplugged post-boot. Called once per hotplugged
278
+ /// vcpu.
279
+ ///
280
+ /// # Arguments
281
+ ///
282
+ /// * `vcpu_config` - The config to be applied to the vCPU, defined at boot time.
283
+ pub fn hotplug_configure (
284
+ & mut self ,
285
+ vcpu_config : & VcpuConfig ,
286
+ ) -> Result < ( ) , KvmVcpuConfigureError > {
287
+ let msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
288
+ let ( kvm_msrs, _) = self . configure_common ( vcpu_config, msrs) ?;
289
+
290
+ crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
291
+ crate :: arch:: x86_64:: interrupts:: set_lint ( & self . fd ) ?;
292
+
293
+ Ok ( ( ) )
294
+ }
295
+
260
296
/// Sets a Port Mapped IO bus for this vcpu.
261
297
pub fn set_pio_bus ( & mut self , pio_bus : crate :: devices:: Bus ) {
262
298
self . peripherals . pio_bus = Some ( pio_bus) ;
0 commit comments