@@ -9,8 +9,8 @@ use std::collections::{HashMap, HashSet};
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} ;
@@ -165,22 +165,17 @@ impl KvmVcpu {
165165 } )
166166 }
167167
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
170170 /// # 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 (
177174 & mut self ,
178- guest_mem : & GuestMemoryMmap ,
179- kernel_start_addr : GuestAddress ,
180175 vcpu_config : & VcpuConfig ,
181- ) -> Result < ( ) , KvmVcpuConfigureError > {
176+ msrs : HashMap < u32 , u64 > ,
177+ ) -> Result < ( Vec < kvm_msr_entry > , CpuId ) , KvmVcpuConfigureError > {
182178 let mut cpuid = vcpu_config. cpu_config . cpuid . clone ( ) ;
183-
184179 // Apply machine specific changes to CPUID.
185180 cpuid. normalize (
186181 // The index of the current logical CPU in the range [0..cpu_count].
@@ -199,6 +194,35 @@ impl KvmVcpu {
199194 . set_cpuid2 ( & kvm_cpuid)
200195 . map_err ( KvmVcpuConfigureError :: SetCpuid ) ?;
201196
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 > {
202226 // Clone MSR entries that are modified by CPU template from `VcpuConfig`.
203227 let mut msrs = vcpu_config. cpu_config . msrs . clone ( ) ;
204228 self . msrs_to_save . extend ( msrs. keys ( ) ) ;
@@ -208,6 +232,8 @@ impl KvmVcpu {
208232 msrs. insert ( entry. index , entry. data ) ;
209233 } ) ;
210234
235+ let ( kvm_msrs, kvm_cpuid) = self . configure_common ( vcpu_config, msrs) ?;
236+
211237 // TODO - Add/amend MSRs for vCPUs based on cpu_config
212238 // By this point the Guest CPUID is established. Some CPU features require MSRs
213239 // to configure and interact with those features. If a MSR is writable from
@@ -226,15 +252,6 @@ impl KvmVcpu {
226252 // save is `architectural MSRs` + `MSRs inferred through CPUID` + `other
227253 // MSRs defined by the template`
228254
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-
238255 crate :: arch:: x86_64:: msr:: set_msrs ( & self . fd , & kvm_msrs) ?;
239256 crate :: arch:: x86_64:: regs:: setup_regs ( & self . fd , kernel_start_addr. raw_value ( ) ) ?;
240257 crate :: arch:: x86_64:: regs:: setup_fpu ( & self . fd ) ?;
@@ -244,6 +261,25 @@ impl KvmVcpu {
244261 Ok ( ( ) )
245262 }
246263
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+
247283 /// Sets a Port Mapped IO bus for this vcpu.
248284 pub fn set_pio_bus ( & mut self , pio_bus : crate :: devices:: Bus ) {
249285 self . peripherals . pio_bus = Some ( pio_bus) ;
0 commit comments