@@ -29,6 +29,8 @@ use vm_superio::Serial;
29
29
30
30
#[ cfg( target_arch = "x86_64" ) ]
31
31
use crate :: acpi;
32
+ #[ cfg( target_arch = "x86_64" ) ]
33
+ use crate :: arch:: DeviceType ;
32
34
use crate :: arch:: InitrdConfig ;
33
35
#[ cfg( target_arch = "aarch64" ) ]
34
36
use crate :: construct_kvm_mpidrs;
@@ -48,6 +50,8 @@ use crate::device_manager::persist::{
48
50
} ;
49
51
use crate :: device_manager:: resources:: ResourceAllocator ;
50
52
#[ cfg( target_arch = "x86_64" ) ]
53
+ use crate :: devices:: acpi:: cpu_container:: { CpuContainer , CpuContainerError } ;
54
+ #[ cfg( target_arch = "x86_64" ) ]
51
55
use crate :: devices:: acpi:: vmgenid:: { VmGenId , VmGenIdError } ;
52
56
use crate :: devices:: legacy:: serial:: SerialOut ;
53
57
#[ cfg( target_arch = "aarch64" ) ]
@@ -96,6 +100,9 @@ pub enum StartMicrovmError {
96
100
/// Error creating VMGenID device: {0}
97
101
#[ cfg( target_arch = "x86_64" ) ]
98
102
CreateVMGenID ( VmGenIdError ) ,
103
+ /// Error creating CpuContainer device: {0}
104
+ #[ cfg( target_arch = "x86_64" ) ]
105
+ CreateCpuContainer ( #[ from] CpuContainerError ) ,
99
106
/// Invalid Memory Configuration: {0}
100
107
GuestMemory ( crate :: vstate:: memory:: MemoryError ) ,
101
108
/// Cannot load initrd due to an invalid memory configuration.
@@ -156,6 +163,7 @@ fn create_vmm_and_vcpus(
156
163
vcpu_count : u8 ,
157
164
#[ cfg( target_arch = "x86_64" ) ] seccomp_filters : BpfThreadMap ,
158
165
kvm_capabilities : Vec < KvmCapability > ,
166
+ boot_timer_enabled : bool ,
159
167
) -> Result < ( Vmm , Vec < Vcpu > ) , StartMicrovmError > {
160
168
use self :: StartMicrovmError :: * ;
161
169
@@ -172,14 +180,28 @@ fn create_vmm_and_vcpus(
172
180
. map_err ( VmmError :: EventFd )
173
181
. map_err ( Internal ) ?;
174
182
175
- let resource_allocator = ResourceAllocator :: new ( ) ?;
183
+ let mut resource_allocator = ResourceAllocator :: new ( ) ?;
176
184
177
185
// 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
+ }
179
195
180
196
// Instantiate ACPI device manager.
181
197
#[ 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
+ } ;
183
205
184
206
// For x86_64 we need to create the interrupt controller before calling `KVM_CREATE_VCPUS`
185
207
// while on aarch64 we need to do it the other way around.
@@ -317,14 +339,18 @@ pub fn build_microvm_for_boot(
317
339
#[ cfg( target_arch = "x86_64" ) ]
318
340
seccomp_filters. clone ( ) ,
319
341
cpu_template. kvm_capabilities . clone ( ) ,
342
+ vm_resources. boot_timer ,
320
343
) ?;
321
344
322
345
// The boot timer device needs to be the first device attached in order
323
346
// to maintain the same MMIO address referenced in the documentation
324
347
// 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) ?;
328
354
329
355
if let Some ( balloon) = vm_resources. balloon . get ( ) {
330
356
attach_balloon_device ( & mut vmm, & mut boot_cmdline, balloon, event_manager) ?;
@@ -488,6 +514,7 @@ pub fn build_microvm_from_snapshot(
488
514
#[ cfg( target_arch = "x86_64" ) ]
489
515
seccomp_filters. clone ( ) ,
490
516
microvm_state. vm_state . kvm_cap_modifiers . clone ( ) ,
517
+ vm_resources. boot_timer ,
491
518
) ?;
492
519
493
520
#[ cfg( target_arch = "x86_64" ) ]
@@ -1048,6 +1075,8 @@ pub mod tests {
1048
1075
use super :: * ;
1049
1076
use crate :: arch:: DeviceType ;
1050
1077
use crate :: device_manager:: resources:: ResourceAllocator ;
1078
+ #[ cfg( target_arch = "x86_64" ) ]
1079
+ use crate :: devices:: acpi:: cpu_container:: CpuContainer ;
1051
1080
use crate :: devices:: virtio:: block:: CacheType ;
1052
1081
use crate :: devices:: virtio:: rng:: device:: ENTROPY_DEV_ID ;
1053
1082
use crate :: devices:: virtio:: vsock:: { TYPE_VSOCK , VSOCK_DEV_ID } ;
@@ -1126,9 +1155,27 @@ pub mod tests {
1126
1155
1127
1156
let mut vm = Vm :: new ( vec ! [ ] ) . unwrap ( ) ;
1128
1157
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
+
1129
1164
let mmio_device_manager = MMIODeviceManager :: new ( ) ;
1165
+
1166
+ #[ cfg( target_arch = "x86_64" ) ]
1167
+ setup_interrupt_controller ( & mut vm) . unwrap ( ) ;
1168
+
1130
1169
#[ 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
+
1132
1179
#[ cfg( target_arch = "x86_64" ) ]
1133
1180
let pio_device_manager = PortIODeviceManager :: new (
1134
1181
Arc :: new ( Mutex :: new ( SerialWrapper {
@@ -1145,9 +1192,6 @@ pub mod tests {
1145
1192
)
1146
1193
. unwrap ( ) ;
1147
1194
1148
- #[ cfg( target_arch = "x86_64" ) ]
1149
- setup_interrupt_controller ( & mut vm) . unwrap ( ) ;
1150
-
1151
1195
#[ cfg( target_arch = "aarch64" ) ]
1152
1196
{
1153
1197
let exit_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
@@ -1166,7 +1210,7 @@ pub mod tests {
1166
1210
vcpus_exit_evt,
1167
1211
#[ cfg( target_arch = "x86_64" ) ]
1168
1212
seccomp_filters : crate :: seccomp_filters:: get_empty_filters ( ) ,
1169
- resource_allocator : ResourceAllocator :: new ( ) . unwrap ( ) ,
1213
+ resource_allocator,
1170
1214
mmio_device_manager,
1171
1215
#[ cfg( target_arch = "x86_64" ) ]
1172
1216
pio_device_manager,
0 commit comments