1#![allow(missing_docs)]
5
6use std::sync::{Arc, Mutex};
7
8use vm_memory::{GuestAddress, GuestRegionCollection};
9use vmm_sys_util::tempdir::TempDir;
10
11use crate::builder::build_microvm_for_boot;
12use crate::resources::VmResources;
13use crate::seccomp::get_empty_filters;
14use crate::test_utils::mock_resources::{MockBootSourceConfig, MockVmConfig, MockVmResources};
15use crate::vmm_config::boot_source::BootSourceConfig;
16use crate::vmm_config::instance_info::InstanceInfo;
17use crate::vmm_config::machine_config::HugePageConfig;
18use crate::vmm_config::memory_hotplug::MemoryHotplugConfig;
19use crate::vstate::memory::{self, GuestMemoryMmap, GuestRegionMmap, GuestRegionMmapExt};
20use crate::{EventManager, Vmm};
21
22pub mod mock_resources;
23
24pub fn single_region_mem(region_size: usize) -> GuestMemoryMmap {
27 single_region_mem_at(0, region_size)
28}
29
30pub fn single_region_mem_raw(region_size: usize) -> Vec<GuestRegionMmap> {
31 single_region_mem_at_raw(0, region_size)
32}
33
34pub fn single_region_mem_at(at: u64, size: usize) -> GuestMemoryMmap {
37 multi_region_mem(&[(GuestAddress(at), size)])
38}
39
40pub fn single_region_mem_at_raw(at: u64, size: usize) -> Vec<GuestRegionMmap> {
41 multi_region_mem_raw(&[(GuestAddress(at), size)])
42}
43
44pub fn multi_region_mem(regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap {
46 GuestRegionCollection::from_regions(
47 memory::anonymous(regions.iter().copied(), false, HugePageConfig::None)
48 .expect("Cannot initialize memory")
49 .into_iter()
50 .map(|region| GuestRegionMmapExt::dram_from_mmap_region(region, 0))
51 .collect(),
52 )
53 .unwrap()
54}
55
56pub fn multi_region_mem_raw(regions: &[(GuestAddress, usize)]) -> Vec<GuestRegionMmap> {
57 memory::anonymous(regions.iter().copied(), false, HugePageConfig::None)
58 .expect("Cannot initialize memory")
59}
60
61pub fn arch_mem(mem_size_bytes: usize) -> GuestMemoryMmap {
64 multi_region_mem(&crate::arch::arch_memory_regions(mem_size_bytes))
65}
66
67pub fn arch_mem_raw(mem_size_bytes: usize) -> Vec<GuestRegionMmap> {
68 multi_region_mem_raw(&crate::arch::arch_memory_regions(mem_size_bytes))
69}
70
71pub fn create_vmm(
72 _kernel_image: Option<&str>,
73 is_diff: bool,
74 boot_microvm: bool,
75 pci_enabled: bool,
76 memory_hotplug_enabled: bool,
77) -> (Arc<Mutex<Vmm>>, EventManager) {
78 let mut event_manager = EventManager::new().unwrap();
79 let empty_seccomp_filters = get_empty_filters();
80
81 let boot_source_cfg = MockBootSourceConfig::new().with_default_boot_args();
82 #[cfg(target_arch = "aarch64")]
83 let boot_source_cfg: BootSourceConfig = boot_source_cfg.into();
84 #[cfg(target_arch = "x86_64")]
85 let boot_source_cfg: BootSourceConfig = match _kernel_image {
86 Some(kernel) => boot_source_cfg.with_kernel(kernel).into(),
87 None => boot_source_cfg.into(),
88 };
89 let mock_vm_res = MockVmResources::new().with_boot_source(boot_source_cfg);
90 let mut resources: VmResources = if is_diff {
91 mock_vm_res
92 .with_vm_config(MockVmConfig::new().with_dirty_page_tracking().into())
93 .into()
94 } else {
95 mock_vm_res.into()
96 };
97
98 resources.pci_enabled = pci_enabled;
99
100 if memory_hotplug_enabled {
101 resources.memory_hotplug = Some(MemoryHotplugConfig {
102 total_size_mib: 1024,
103 block_size_mib: 2,
104 slot_size_mib: 128,
105 });
106 }
107
108 let vmm = build_microvm_for_boot(
109 &InstanceInfo::default(),
110 &resources,
111 &mut event_manager,
112 &empty_seccomp_filters,
113 )
114 .unwrap();
115
116 if boot_microvm {
117 vmm.lock().unwrap().resume_vm().unwrap();
118 }
119
120 (vmm, event_manager)
121}
122
123pub fn default_vmm(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
124 create_vmm(kernel_image, false, true, false, false)
125}
126
127pub fn default_vmm_no_boot(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
128 create_vmm(kernel_image, false, false, false, false)
129}
130
131pub fn dirty_tracking_vmm(kernel_image: Option<&str>) -> (Arc<Mutex<Vmm>>, EventManager) {
132 create_vmm(kernel_image, true, true, false, false)
133}
134
135#[allow(clippy::undocumented_unsafe_blocks)]
136#[allow(clippy::cast_possible_truncation)]
137pub fn create_tmp_socket() -> (TempDir, String) {
138 let tmp_dir = TempDir::new().unwrap();
139 let tmp_dir_path_str = tmp_dir.as_path().to_str().unwrap();
140 let tmp_socket_path = format!("{tmp_dir_path_str}/tmp_socket");
141
142 unsafe {
143 let socketfd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
144 if socketfd < 0 {
145 panic!("Cannot create socket");
146 }
147 let mut socket_addr = libc::sockaddr_un {
148 sun_family: libc::AF_UNIX as u16,
149 sun_path: [0; 108],
150 };
151
152 std::ptr::copy(
153 tmp_socket_path.as_ptr().cast(),
154 socket_addr.sun_path.as_mut_ptr(),
155 tmp_socket_path.len(),
156 );
157
158 let bind = libc::bind(
159 socketfd,
160 (&socket_addr as *const libc::sockaddr_un).cast(),
161 std::mem::size_of::<libc::sockaddr_un>() as u32,
162 );
163 if bind < 0 {
164 panic!("Cannot bind socket");
165 }
166
167 let listen = libc::listen(socketfd, 1);
168 if listen < 0 {
169 panic!("Cannot listen on socket");
170 }
171 }
172
173 (tmp_dir, tmp_socket_path)
174}