@@ -907,6 +907,16 @@ impl Vmm {
907
907
let arch_mem_regions = arch:: arch_memory_regions ( mem_size) ;
908
908
self . guest_memory =
909
909
Some ( GuestMemory :: new ( & arch_mem_regions) . map_err ( StartMicrovmError :: GuestMemory ) ?) ;
910
+ self . vm
911
+ . memory_init (
912
+ self . guest_memory
913
+ . clone ( )
914
+ . ok_or ( StartMicrovmError :: GuestMemory (
915
+ memory_model:: GuestMemoryError :: MemoryNotInitialized ,
916
+ ) ) ?,
917
+ & self . kvm ,
918
+ )
919
+ . map_err ( StartMicrovmError :: ConfigureVm ) ?;
910
920
Ok ( ( ) )
911
921
}
912
922
@@ -917,7 +927,7 @@ impl Vmm {
917
927
Ok ( ( ) )
918
928
}
919
929
920
- fn init_devices ( & mut self ) -> std:: result:: Result < ( ) , StartMicrovmError > {
930
+ fn attach_virtio_devices ( & mut self ) -> std:: result:: Result < ( ) , StartMicrovmError > {
921
931
let guest_mem = self
922
932
. guest_memory
923
933
. clone ( )
@@ -938,21 +948,18 @@ impl Vmm {
938
948
#[ cfg( feature = "vsock" ) ]
939
949
self . attach_vsock_devices ( & mut device_manager, & guest_mem) ?;
940
950
951
+ // Register the associated IRQ events and IO events for the virtio devices.
952
+ for request in & device_manager. vm_requests {
953
+ if let VmResponse :: Err ( e) = request. execute ( self . vm . get_fd ( ) ) {
954
+ return Err ( StartMicrovmError :: DeviceVmRequest ( e) ) ?;
955
+ }
956
+ }
957
+
941
958
self . mmio_device_manager = Some ( device_manager) ;
942
959
Ok ( ( ) )
943
960
}
944
961
945
- fn init_microvm ( & mut self ) -> std:: result:: Result < ( ) , StartMicrovmError > {
946
- self . vm
947
- . memory_init (
948
- self . guest_memory
949
- . clone ( )
950
- . ok_or ( StartMicrovmError :: GuestMemory (
951
- memory_model:: GuestMemoryError :: MemoryNotInitialized ,
952
- ) ) ?,
953
- & self . kvm ,
954
- )
955
- . map_err ( StartMicrovmError :: ConfigureVm ) ?;
962
+ fn setup_interrupt_controller ( & mut self ) -> std:: result:: Result < ( ) , StartMicrovmError > {
956
963
self . vm
957
964
. setup_irqchip (
958
965
& self . legacy_device_manager . com_evt_1_3 ,
@@ -964,18 +971,10 @@ impl Vmm {
964
971
self . vm
965
972
. create_pit ( )
966
973
. map_err ( StartMicrovmError :: ConfigureVm ) ?;
974
+ Ok ( ( ) )
975
+ }
967
976
968
- // mmio_device_manager is instantiated in init_devices, which is called before init_microvm.
969
- let device_manager = self
970
- . mmio_device_manager
971
- . as_ref ( )
972
- . ok_or ( StartMicrovmError :: DeviceManager ) ?;
973
- for request in & device_manager. vm_requests {
974
- if let VmResponse :: Err ( e) = request. execute ( self . vm . get_fd ( ) ) {
975
- return Err ( StartMicrovmError :: DeviceVmRequest ( e) ) ?;
976
- }
977
- }
978
-
977
+ fn attach_legacy_devices ( & mut self ) -> std:: result:: Result < ( ) , StartMicrovmError > {
979
978
self . legacy_device_manager
980
979
. register_devices ( )
981
980
. map_err ( StartMicrovmError :: LegacyIOBus ) ?;
@@ -1273,9 +1272,12 @@ impl Vmm {
1273
1272
self . init_guest_memory ( )
1274
1273
. map_err ( |e| VmmActionError :: StartMicrovm ( ErrorKind :: Internal , e) ) ?;
1275
1274
1276
- self . init_devices ( )
1275
+ self . setup_interrupt_controller ( )
1276
+ . map_err ( |e| VmmActionError :: StartMicrovm ( ErrorKind :: Internal , e) ) ?;
1277
+
1278
+ self . attach_virtio_devices ( )
1277
1279
. map_err ( |e| VmmActionError :: StartMicrovm ( ErrorKind :: Internal , e) ) ?;
1278
- self . init_microvm ( )
1280
+ self . attach_legacy_devices ( )
1279
1281
. map_err ( |e| VmmActionError :: StartMicrovm ( ErrorKind :: Internal , e) ) ?;
1280
1282
1281
1283
let entry_addr = self
@@ -2809,7 +2811,7 @@ mod tests {
2809
2811
vmm. default_kernel_config ( ) ;
2810
2812
assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
2811
2813
2812
- assert ! ( vmm. init_devices ( ) . is_ok( ) ) ;
2814
+ assert ! ( vmm. attach_virtio_devices ( ) . is_ok( ) ) ;
2813
2815
}
2814
2816
2815
2817
#[ test]
@@ -3039,21 +3041,15 @@ mod tests {
3039
3041
// Booting an actual guest and getting real data is covered by `kvm::tests::run_code_test`.
3040
3042
}
3041
3043
3042
- #[ cfg( target_arch = "x86_64" ) ]
3043
3044
#[ test]
3044
3045
fn test_create_vcpus ( ) {
3045
3046
let mut vmm = create_vmm_object ( InstanceState :: Uninitialized ) ;
3046
3047
vmm. default_kernel_config ( ) ;
3047
3048
3048
3049
assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
3049
- assert ! ( vmm. guest_memory. is_some( ) ) ;
3050
- let kvm = KvmContext :: new ( ) . unwrap ( ) ;
3051
- let guest_mem = vmm. guest_memory . clone ( ) . unwrap ( ) ;
3052
-
3053
- vmm. vm
3054
- . memory_init ( guest_mem. clone ( ) , & kvm)
3055
- . expect ( "Cannot initialize memory for test vm" ) ;
3056
3050
assert ! ( vmm. vm. get_memory( ) . is_some( ) ) ;
3051
+
3052
+ #[ cfg( target_arch = "x86_64" ) ]
3057
3053
// `KVM_CREATE_VCPU` fails if the irqchip is not created beforehand. This is x86_64 speciifc.
3058
3054
vmm. vm
3059
3055
. setup_irqchip (
@@ -3064,4 +3060,50 @@ mod tests {
3064
3060
. expect ( "Cannot create IRQCHIP" ) ;
3065
3061
assert ! ( vmm. create_vcpus( GuestAddress ( 0x0 ) ) . is_ok( ) ) ;
3066
3062
}
3063
+
3064
+ #[ test]
3065
+ fn test_setup_interrupt_controller ( ) {
3066
+ let mut vmm = create_vmm_object ( InstanceState :: Uninitialized ) ;
3067
+ assert ! ( vmm. setup_interrupt_controller( ) . is_ok( ) ) ;
3068
+ }
3069
+
3070
+ #[ test]
3071
+ fn test_attach_virtio_devices ( ) {
3072
+ let mut vmm = create_vmm_object ( InstanceState :: Uninitialized ) ;
3073
+ vmm. default_kernel_config ( ) ;
3074
+
3075
+ assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
3076
+ assert ! ( vmm. vm. get_memory( ) . is_some( ) ) ;
3077
+
3078
+ // Create test network interface.
3079
+ let network_interface = NetworkInterfaceConfig {
3080
+ iface_id : String :: from ( "netif" ) ,
3081
+ host_dev_name : String :: from ( "hostname" ) ,
3082
+ guest_mac : None ,
3083
+ rx_rate_limiter : None ,
3084
+ tx_rate_limiter : None ,
3085
+ allow_mmds_requests : false ,
3086
+ tap : None ,
3087
+ } ;
3088
+
3089
+ assert ! ( vmm. insert_net_device( network_interface) . is_ok( ) ) ;
3090
+ assert ! ( vmm. attach_virtio_devices( ) . is_ok( ) ) ;
3091
+ assert ! ( vmm. mmio_device_manager. is_some( ) ) ;
3092
+ // 2 io events and 1 irq event.
3093
+ assert ! ( vmm. mmio_device_manager. unwrap( ) . vm_requests. len( ) == 3 ) ;
3094
+ }
3095
+
3096
+ #[ test]
3097
+ fn test_attach_legacy_devices ( ) {
3098
+ let mut vmm = create_vmm_object ( InstanceState :: Uninitialized ) ;
3099
+
3100
+ assert ! ( vmm. attach_legacy_devices( ) . is_ok( ) ) ;
3101
+ assert ! ( vmm. legacy_device_manager. io_bus. get_device( 0x3f8 ) . is_some( ) ) ;
3102
+ assert ! ( vmm. legacy_device_manager. io_bus. get_device( 0x2f8 ) . is_some( ) ) ;
3103
+ assert ! ( vmm. legacy_device_manager. io_bus. get_device( 0x3e8 ) . is_some( ) ) ;
3104
+ assert ! ( vmm. legacy_device_manager. io_bus. get_device( 0x2e8 ) . is_some( ) ) ;
3105
+ assert ! ( vmm. legacy_device_manager. io_bus. get_device( 0x060 ) . is_some( ) ) ;
3106
+ let stdin_handle = io:: stdin ( ) ;
3107
+ stdin_handle. lock ( ) . set_canon_mode ( ) . unwrap ( ) ;
3108
+ }
3067
3109
}
0 commit comments