@@ -9,8 +9,8 @@ use std::collections::BTreeMap;
99use std:: fmt:: Debug ;
1010
1111use 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 ,
1414} ;
1515use kvm_ioctls:: { VcpuExit , VcpuFd } ;
1616use log:: { error, warn} ;
@@ -178,22 +178,17 @@ impl KvmVcpu {
178178 } )
179179 }
180180
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
183183 /// # 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 (
190187 & mut self ,
191- guest_mem : & GuestMemoryMmap ,
192- kernel_start_addr : GuestAddress ,
193188 vcpu_config : & VcpuConfig ,
194- ) -> Result < ( ) , KvmVcpuConfigureError > {
189+ msrs : std:: collections:: BTreeMap < u32 , u64 > ,
190+ ) -> Result < ( Vec < kvm_msr_entry > , CpuId ) , KvmVcpuConfigureError > {
195191 let mut cpuid = vcpu_config. cpu_config . cpuid . clone ( ) ;
196-
197192 // Apply machine specific changes to CPUID.
198193 cpuid. normalize (
199194 // The index of the current logical CPU in the range [0..cpu_count].
@@ -212,6 +207,35 @@ impl KvmVcpu {
212207 . set_cpuid2 ( & kvm_cpuid)
213208 . map_err ( KvmVcpuConfigureError :: SetCpuid ) ?;
214209
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 > {
215239 // Clone MSR entries that are modified by CPU template from `VcpuConfig`.
216240 let mut msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
217241 self . msrs_to_save . extend ( msrs. keys ( ) ) ;
@@ -221,6 +245,8 @@ impl KvmVcpu {
221245 msrs. insert ( entry. index , entry. data ) ;
222246 } ) ;
223247
248+ let ( kvm_msrs, kvm_cpuid) = self . configure_common ( vcpu_config, msrs) ?;
249+
224250 // TODO - Add/amend MSRs for vCPUs based on cpu_config
225251 // By this point the Guest CPUID is established. Some CPU features require MSRs
226252 // to configure and interact with those features. If a MSR is writable from
@@ -239,15 +265,6 @@ impl KvmVcpu {
239265 // save is `architectural MSRs` + `MSRs inferred through CPUID` + `other
240266 // MSRs defined by the template`
241267
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-
251268 crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
252269 crate :: arch:: x86_64:: regs:: setup_regs ( & self . fd , kernel_start_addr. raw_value ( ) ) ?;
253270 crate :: arch:: x86_64:: regs:: setup_fpu ( & self . fd ) ?;
@@ -257,6 +274,25 @@ impl KvmVcpu {
257274 Ok ( ( ) )
258275 }
259276
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+
260296 /// Sets a Port Mapped IO bus for this vcpu.
261297 pub fn set_pio_bus ( & mut self , pio_bus : crate :: devices:: Bus ) {
262298 self . peripherals . pio_bus = Some ( pio_bus) ;
0 commit comments