@@ -29,6 +29,8 @@ use vm_superio::Serial;
2929
3030#[ cfg( target_arch = "x86_64" ) ]
3131use crate :: acpi;
32+ #[ cfg( target_arch = "x86_64" ) ]
33+ use crate :: arch:: DeviceType ;
3234use crate :: arch:: InitrdConfig ;
3335#[ cfg( target_arch = "aarch64" ) ]
3436use crate :: construct_kvm_mpidrs;
@@ -48,6 +50,8 @@ use crate::device_manager::persist::{
4850} ;
4951use crate :: device_manager:: resources:: ResourceAllocator ;
5052#[ cfg( target_arch = "x86_64" ) ]
53+ use crate :: devices:: acpi:: cpu_container:: { CpuContainer , CpuContainerError } ;
54+ #[ cfg( target_arch = "x86_64" ) ]
5155use crate :: devices:: acpi:: vmgenid:: { VmGenId , VmGenIdError } ;
5256use crate :: devices:: legacy:: serial:: SerialOut ;
5357#[ cfg( target_arch = "aarch64" ) ]
@@ -96,6 +100,9 @@ pub enum StartMicrovmError {
96100 /// Error creating VMGenID device: {0}
97101 #[ cfg( target_arch = "x86_64" ) ]
98102 CreateVMGenID ( VmGenIdError ) ,
103+ /// Error creating CpuContainer device: {0}
104+ #[ cfg( target_arch = "x86_64" ) ]
105+ CreateCpuContainer ( #[ from] CpuContainerError ) ,
99106 /// Invalid Memory Configuration: {0}
100107 GuestMemory ( crate :: vstate:: memory:: MemoryError ) ,
101108 /// Cannot load initrd due to an invalid memory configuration.
@@ -156,6 +163,7 @@ fn create_vmm_and_vcpus(
156163 vcpu_count : u8 ,
157164 #[ cfg( target_arch = "x86_64" ) ] seccomp_filters : BpfThreadMap ,
158165 kvm_capabilities : Vec < KvmCapability > ,
166+ boot_timer_enabled : bool ,
159167) -> Result < ( Vmm , Vec < Vcpu > ) , StartMicrovmError > {
160168 use self :: StartMicrovmError :: * ;
161169
@@ -172,14 +180,28 @@ fn create_vmm_and_vcpus(
172180 . map_err ( VmmError :: EventFd )
173181 . map_err ( Internal ) ?;
174182
175- let resource_allocator = ResourceAllocator :: new ( ) ?;
183+ let mut resource_allocator = ResourceAllocator :: new ( ) ?;
176184
177185 // Instantiate the MMIO device manager.
178- let mmio_device_manager = MMIODeviceManager :: new ( ) ;
186+ let mut mmio_device_manager = MMIODeviceManager :: new ( ) ;
187+
188+ if boot_timer_enabled {
189+ let boot_timer = crate :: devices:: pseudo:: BootTimer :: new ( TimestampUs :: default ( ) ) ;
190+
191+ mmio_device_manager
192+ . register_mmio_boot_timer ( & mut resource_allocator, boot_timer)
193+ . map_err ( RegisterMmioDevice ) ?;
194+ }
179195
180196 // Instantiate ACPI device manager.
181197 #[ cfg( target_arch = "x86_64" ) ]
182- let acpi_device_manager = ACPIDeviceManager :: new ( ) ;
198+ let acpi_device_manager = {
199+ let cpu_container = Arc :: new ( Mutex :: new ( CpuContainer :: new (
200+ & mut resource_allocator,
201+ vcpu_count,
202+ ) ?) ) ;
203+ ACPIDeviceManager :: new ( cpu_container)
204+ } ;
183205
184206 // For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS`
185207 // while on aarch64 we need to do it the other way around.
@@ -317,14 +339,18 @@ pub fn build_microvm_for_boot(
317339 #[ cfg( target_arch = "x86_64" ) ]
318340 seccomp_filters. clone ( ) ,
319341 cpu_template. kvm_capabilities . clone ( ) ,
342+ vm_resources. boot_timer ,
320343 ) ?;
321344
322345 // The boot timer device needs to be the first device attached in order
323346 // to maintain the same MMIO address referenced in the documentation
324347 // and tests.
325- if vm_resources. boot_timer {
326- attach_boot_timer_device ( & mut vmm, request_ts) ?;
327- }
348+ // if vm_resources.boot_timer {
349+ // attach_boot_timer_device(&mut vmm, request_ts)?;
350+ // }
351+
352+ #[ cfg( target_arch = "x86_64" ) ]
353+ attach_cpu_container_device ( & mut vmm) ?;
328354
329355 if let Some ( balloon) = vm_resources. balloon . get ( ) {
330356 attach_balloon_device ( & mut vmm, & mut boot_cmdline, balloon, event_manager) ?;
@@ -488,6 +514,7 @@ pub fn build_microvm_from_snapshot(
488514 #[ cfg( target_arch = "x86_64" ) ]
489515 seccomp_filters. clone ( ) ,
490516 microvm_state. vm_state . kvm_cap_modifiers . clone ( ) ,
517+ vm_resources. boot_timer ,
491518 ) ?;
492519
493520 #[ cfg( target_arch = "x86_64" ) ]
@@ -1048,6 +1075,8 @@ pub mod tests {
10481075 use super :: * ;
10491076 use crate :: arch:: DeviceType ;
10501077 use crate :: device_manager:: resources:: ResourceAllocator ;
1078+ #[ cfg( target_arch = "x86_64" ) ]
1079+ use crate :: devices:: acpi:: cpu_container:: CpuContainer ;
10511080 use crate :: devices:: virtio:: block:: CacheType ;
10521081 use crate :: devices:: virtio:: rng:: device:: ENTROPY_DEV_ID ;
10531082 use crate :: devices:: virtio:: vsock:: { TYPE_VSOCK , VSOCK_DEV_ID } ;
@@ -1126,9 +1155,27 @@ pub mod tests {
11261155
11271156 let mut vm = Vm :: new ( vec ! [ ] ) . unwrap ( ) ;
11281157 vm. memory_init ( & guest_memory, false ) . unwrap ( ) ;
1158+
1159+ #[ cfg( target_arch = "x86_64" ) ]
1160+ let mut resource_allocator = ResourceAllocator :: new ( ) . unwrap ( ) ;
1161+ #[ cfg( target_arch = "aarch64" ) ]
1162+ let resource_allocator = ResourceAllocator :: new ( ) . unwrap ( ) ;
1163+
11291164 let mmio_device_manager = MMIODeviceManager :: new ( ) ;
1165+
1166+ #[ cfg( target_arch = "x86_64" ) ]
1167+ setup_interrupt_controller ( & mut vm) . unwrap ( ) ;
1168+
11301169 #[ cfg( target_arch = "x86_64" ) ]
1131- let acpi_device_manager = ACPIDeviceManager :: new ( ) ;
1170+ let acpi_device_manager = {
1171+ let cpu_container = Arc :: new ( Mutex :: new (
1172+ CpuContainer :: new ( & mut resource_allocator, 1 )
1173+ . map_err ( StartMicrovmError :: CreateCpuContainer )
1174+ . unwrap ( ) ,
1175+ ) ) ;
1176+ ACPIDeviceManager :: new ( cpu_container)
1177+ } ;
1178+
11321179 #[ cfg( target_arch = "x86_64" ) ]
11331180 let pio_device_manager = PortIODeviceManager :: new (
11341181 Arc :: new ( Mutex :: new ( SerialWrapper {
@@ -1145,9 +1192,6 @@ pub mod tests {
11451192 )
11461193 . unwrap ( ) ;
11471194
1148- #[ cfg( target_arch = "x86_64" ) ]
1149- setup_interrupt_controller ( & mut vm) . unwrap ( ) ;
1150-
11511195 #[ cfg( target_arch = "aarch64" ) ]
11521196 {
11531197 let exit_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
@@ -1166,7 +1210,7 @@ pub mod tests {
11661210 vcpus_exit_evt,
11671211 #[ cfg( target_arch = "x86_64" ) ]
11681212 seccomp_filters : crate :: seccomp_filters:: get_empty_filters ( ) ,
1169- resource_allocator : ResourceAllocator :: new ( ) . unwrap ( ) ,
1213+ resource_allocator,
11701214 mmio_device_manager,
11711215 #[ cfg( target_arch = "x86_64" ) ]
11721216 pio_device_manager,
0 commit comments