xref: /aosp_15_r20/external/crosvm/hypervisor/src/haxm/vm.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use core::ffi::c_void;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Reverse;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BinaryHeap;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use base::errno_result;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_mut_ref;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::MappedRegion;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::MmapError;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
25*bb4ee6a4SAndroid Build Coastguard Worker use fnv::FnvHashMap;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::E2BIG;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::EEXIST;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::EFAULT;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
30*bb4ee6a4SAndroid Build Coastguard Worker use libc::EIO;
31*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOENT;
32*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOSPC;
33*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOTSUP;
34*bb4ee6a4SAndroid Build Coastguard Worker use libc::EOVERFLOW;
35*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
36*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
37*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
38*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
39*bb4ee6a4SAndroid Build Coastguard Worker use win_util::win32_wide_string;
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::host_phys_addr_bits;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::ClockState;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::Datamatch;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceKind;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::Hypervisor;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoEventAddress;
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemCacheType;
49*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemSlot;
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuX86_64;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vm;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmCap;
53*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmX86_64;
54*bb4ee6a4SAndroid Build Coastguard Worker 
55*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper around creating and using a HAXM VM.
56*bb4ee6a4SAndroid Build Coastguard Worker pub struct HaxmVm {
57*bb4ee6a4SAndroid Build Coastguard Worker     haxm: Haxm,
58*bb4ee6a4SAndroid Build Coastguard Worker     vm_id: u32,
59*bb4ee6a4SAndroid Build Coastguard Worker     descriptor: SafeDescriptor,
60*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: GuestMemory,
61*bb4ee6a4SAndroid Build Coastguard Worker     mem_regions: Arc<Mutex<BTreeMap<MemSlot, (GuestAddress, Box<dyn MappedRegion>)>>>,
62*bb4ee6a4SAndroid Build Coastguard Worker     /// A min heap of MemSlot numbers that were used and then removed and can now be re-used
63*bb4ee6a4SAndroid Build Coastguard Worker     mem_slot_gaps: Arc<Mutex<BinaryHeap<Reverse<MemSlot>>>>,
64*bb4ee6a4SAndroid Build Coastguard Worker     // HAXM's implementation of ioevents makes several assumptions about how crosvm uses ioevents:
65*bb4ee6a4SAndroid Build Coastguard Worker     //   1. All ioevents are registered during device setup, and thus can be cloned when the vm is
66*bb4ee6a4SAndroid Build Coastguard Worker     //      cloned instead of locked in an Arc<Mutex<>>. This will make handling ioevents in each
67*bb4ee6a4SAndroid Build Coastguard Worker     //      vcpu thread easier because no locks will need to be acquired.
68*bb4ee6a4SAndroid Build Coastguard Worker     //   2. All ioevents use Datamatch::AnyLength. We don't bother checking the datamatch, which
69*bb4ee6a4SAndroid Build Coastguard Worker     //      will make this faster.
70*bb4ee6a4SAndroid Build Coastguard Worker     //   3. We only ever register one eventfd to each address. This simplifies our data structure.
71*bb4ee6a4SAndroid Build Coastguard Worker     ioevents: FnvHashMap<IoEventAddress, Event>,
72*bb4ee6a4SAndroid Build Coastguard Worker }
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker impl HaxmVm {
75*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a new `HaxmVm` using the given `Haxm` instance.
new(haxm: &Haxm, guest_mem: GuestMemory) -> Result<HaxmVm>76*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(haxm: &Haxm, guest_mem: GuestMemory) -> Result<HaxmVm> {
77*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm_id: u32 = 0;
78*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
79*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we know descriptor is a real haxm descriptor as this module is the only
80*bb4ee6a4SAndroid Build Coastguard Worker         // one that can make Haxm objects.
81*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { ioctl_with_mut_ref(haxm, HAX_IOCTL_CREATE_VM, &mut vm_id) };
82*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
83*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
84*bb4ee6a4SAndroid Build Coastguard Worker         }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker         // Haxm creates additional device paths when VMs are created
87*bb4ee6a4SAndroid Build Coastguard Worker         let vm_descriptor = open_haxm_vm_device(USE_GHAXM.load(Ordering::Relaxed), vm_id)?;
88*bb4ee6a4SAndroid Build Coastguard Worker 
89*bb4ee6a4SAndroid Build Coastguard Worker         for region in guest_mem.regions() {
90*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
91*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because the guest regions are guaranteed not to overlap.
92*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
93*bb4ee6a4SAndroid Build Coastguard Worker                 set_user_memory_region(
94*bb4ee6a4SAndroid Build Coastguard Worker                     &vm_descriptor,
95*bb4ee6a4SAndroid Build Coastguard Worker                     false,
96*bb4ee6a4SAndroid Build Coastguard Worker                     region.guest_addr.offset(),
97*bb4ee6a4SAndroid Build Coastguard Worker                     region.size as u64,
98*bb4ee6a4SAndroid Build Coastguard Worker                     MemoryRegionOp::Add(region.host_addr as *mut u8 as u64),
99*bb4ee6a4SAndroid Build Coastguard Worker                 )
100*bb4ee6a4SAndroid Build Coastguard Worker             }?;
101*bb4ee6a4SAndroid Build Coastguard Worker         }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker         Ok(HaxmVm {
104*bb4ee6a4SAndroid Build Coastguard Worker             vm_id,
105*bb4ee6a4SAndroid Build Coastguard Worker             haxm: haxm.try_clone()?,
106*bb4ee6a4SAndroid Build Coastguard Worker             descriptor: vm_descriptor,
107*bb4ee6a4SAndroid Build Coastguard Worker             guest_mem,
108*bb4ee6a4SAndroid Build Coastguard Worker             mem_regions: Arc::new(Mutex::new(BTreeMap::new())),
109*bb4ee6a4SAndroid Build Coastguard Worker             mem_slot_gaps: Arc::new(Mutex::new(BinaryHeap::new())),
110*bb4ee6a4SAndroid Build Coastguard Worker             ioevents: FnvHashMap::default(),
111*bb4ee6a4SAndroid Build Coastguard Worker         })
112*bb4ee6a4SAndroid Build Coastguard Worker     }
113*bb4ee6a4SAndroid Build Coastguard Worker 
check_raw_capability(&self, cap: u32) -> bool114*bb4ee6a4SAndroid Build Coastguard Worker     pub fn check_raw_capability(&self, cap: u32) -> bool {
115*bb4ee6a4SAndroid Build Coastguard Worker         let mut capability_info = hax_capabilityinfo::default();
116*bb4ee6a4SAndroid Build Coastguard Worker         let ret =
117*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
118*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we know that our file is a VM fd and we verify the return result.
119*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { ioctl_with_mut_ref(&self.haxm, HAX_IOCTL_CAPABILITY, &mut capability_info) };
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
122*bb4ee6a4SAndroid Build Coastguard Worker             return false;
123*bb4ee6a4SAndroid Build Coastguard Worker         }
124*bb4ee6a4SAndroid Build Coastguard Worker 
125*bb4ee6a4SAndroid Build Coastguard Worker         // If wstatus is zero, HAXM is not usable.
126*bb4ee6a4SAndroid Build Coastguard Worker         // In this case, the winfo bits indicate why, rather than communicating capability
127*bb4ee6a4SAndroid Build Coastguard Worker         // information.
128*bb4ee6a4SAndroid Build Coastguard Worker         if capability_info.wstatus == 0 {
129*bb4ee6a4SAndroid Build Coastguard Worker             return false;
130*bb4ee6a4SAndroid Build Coastguard Worker         }
131*bb4ee6a4SAndroid Build Coastguard Worker 
132*bb4ee6a4SAndroid Build Coastguard Worker         (cap & capability_info.winfo as u32) != 0
133*bb4ee6a4SAndroid Build Coastguard Worker     }
134*bb4ee6a4SAndroid Build Coastguard Worker 
register_log_file(&self, path: &str) -> Result<()>135*bb4ee6a4SAndroid Build Coastguard Worker     pub fn register_log_file(&self, path: &str) -> Result<()> {
136*bb4ee6a4SAndroid Build Coastguard Worker         // The IOCTL here is only avilable on internal fork of HAXM and only works on Windows.
137*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)]
138*bb4ee6a4SAndroid Build Coastguard Worker         if get_use_ghaxm() {
139*bb4ee6a4SAndroid Build Coastguard Worker             let mut log_file = hax_log_file::default();
140*bb4ee6a4SAndroid Build Coastguard Worker 
141*bb4ee6a4SAndroid Build Coastguard Worker             // Although it would be more efficient to do this check prior to allocating the log_file
142*bb4ee6a4SAndroid Build Coastguard Worker             // struct, the code would be more complex and less maintainable. This is only ever
143*bb4ee6a4SAndroid Build Coastguard Worker             // called once per-vm so the extra temporary memory and time shouldn't be a
144*bb4ee6a4SAndroid Build Coastguard Worker             // problem.
145*bb4ee6a4SAndroid Build Coastguard Worker             if path.len() >= log_file.path.len() {
146*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::new(E2BIG));
147*bb4ee6a4SAndroid Build Coastguard Worker             }
148*bb4ee6a4SAndroid Build Coastguard Worker 
149*bb4ee6a4SAndroid Build Coastguard Worker             let wstring = &win32_wide_string(path);
150*bb4ee6a4SAndroid Build Coastguard Worker             log_file.path[..wstring.len()].clone_from_slice(wstring);
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
153*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we know that our file is a VM fd and we verify the return result.
154*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe { ioctl_with_ref(self, HAX_VM_IOCTL_REGISTER_LOG_FILE, &log_file) };
155*bb4ee6a4SAndroid Build Coastguard Worker 
156*bb4ee6a4SAndroid Build Coastguard Worker             if ret != 0 {
157*bb4ee6a4SAndroid Build Coastguard Worker                 return errno_result();
158*bb4ee6a4SAndroid Build Coastguard Worker             }
159*bb4ee6a4SAndroid Build Coastguard Worker         }
160*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
161*bb4ee6a4SAndroid Build Coastguard Worker     }
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for HaxmVm {
as_raw_descriptor(&self) -> RawDescriptor165*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
166*bb4ee6a4SAndroid Build Coastguard Worker         self.descriptor.as_raw_descriptor()
167*bb4ee6a4SAndroid Build Coastguard Worker     }
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker enum MemoryRegionOp {
171*bb4ee6a4SAndroid Build Coastguard Worker     // Map a memory region for the given host address.
172*bb4ee6a4SAndroid Build Coastguard Worker     Add(u64),
173*bb4ee6a4SAndroid Build Coastguard Worker     // Remove the memory region.
174*bb4ee6a4SAndroid Build Coastguard Worker     Remove,
175*bb4ee6a4SAndroid Build Coastguard Worker }
176*bb4ee6a4SAndroid Build Coastguard Worker 
set_user_memory_region( descriptor: &SafeDescriptor, read_only: bool, guest_addr: u64, size: u64, op: MemoryRegionOp, ) -> Result<()>177*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn set_user_memory_region(
178*bb4ee6a4SAndroid Build Coastguard Worker     descriptor: &SafeDescriptor,
179*bb4ee6a4SAndroid Build Coastguard Worker     read_only: bool,
180*bb4ee6a4SAndroid Build Coastguard Worker     guest_addr: u64,
181*bb4ee6a4SAndroid Build Coastguard Worker     size: u64,
182*bb4ee6a4SAndroid Build Coastguard Worker     op: MemoryRegionOp,
183*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
184*bb4ee6a4SAndroid Build Coastguard Worker     let (va, flags) = match op {
185*bb4ee6a4SAndroid Build Coastguard Worker         MemoryRegionOp::Add(va) => {
186*bb4ee6a4SAndroid Build Coastguard Worker             let mut flags = HAX_RAM_INFO_STANDALONE;
187*bb4ee6a4SAndroid Build Coastguard Worker             if read_only {
188*bb4ee6a4SAndroid Build Coastguard Worker                 flags |= HAX_RAM_INFO_ROM
189*bb4ee6a4SAndroid Build Coastguard Worker             }
190*bb4ee6a4SAndroid Build Coastguard Worker             (va, flags)
191*bb4ee6a4SAndroid Build Coastguard Worker         }
192*bb4ee6a4SAndroid Build Coastguard Worker         MemoryRegionOp::Remove => (0, HAX_RAM_INFO_INVALID),
193*bb4ee6a4SAndroid Build Coastguard Worker     };
194*bb4ee6a4SAndroid Build Coastguard Worker     let ram_info = hax_set_ram_info2 {
195*bb4ee6a4SAndroid Build Coastguard Worker         pa_start: guest_addr,
196*bb4ee6a4SAndroid Build Coastguard Worker         size,
197*bb4ee6a4SAndroid Build Coastguard Worker         va,
198*bb4ee6a4SAndroid Build Coastguard Worker         flags,
199*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
200*bb4ee6a4SAndroid Build Coastguard Worker     };
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
203*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because we know that our file is a VM fd and we verify the return result.
204*bb4ee6a4SAndroid Build Coastguard Worker     let ret = ioctl_with_ref(descriptor, HAX_VM_IOCTL_SET_RAM2, &ram_info);
205*bb4ee6a4SAndroid Build Coastguard Worker     if ret != 0 {
206*bb4ee6a4SAndroid Build Coastguard Worker         return errno_result();
207*bb4ee6a4SAndroid Build Coastguard Worker     }
208*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker impl Vm for HaxmVm {
try_clone(&self) -> Result<Self>212*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<Self> {
213*bb4ee6a4SAndroid Build Coastguard Worker         let mut ioevents = FnvHashMap::default();
214*bb4ee6a4SAndroid Build Coastguard Worker         for (addr, evt) in self.ioevents.iter() {
215*bb4ee6a4SAndroid Build Coastguard Worker             ioevents.insert(*addr, evt.try_clone()?);
216*bb4ee6a4SAndroid Build Coastguard Worker         }
217*bb4ee6a4SAndroid Build Coastguard Worker         Ok(HaxmVm {
218*bb4ee6a4SAndroid Build Coastguard Worker             vm_id: self.vm_id,
219*bb4ee6a4SAndroid Build Coastguard Worker             haxm: self.haxm.try_clone()?,
220*bb4ee6a4SAndroid Build Coastguard Worker             descriptor: self.descriptor.try_clone()?,
221*bb4ee6a4SAndroid Build Coastguard Worker             guest_mem: self.guest_mem.clone(),
222*bb4ee6a4SAndroid Build Coastguard Worker             mem_regions: self.mem_regions.clone(),
223*bb4ee6a4SAndroid Build Coastguard Worker             mem_slot_gaps: self.mem_slot_gaps.clone(),
224*bb4ee6a4SAndroid Build Coastguard Worker             ioevents,
225*bb4ee6a4SAndroid Build Coastguard Worker         })
226*bb4ee6a4SAndroid Build Coastguard Worker     }
227*bb4ee6a4SAndroid Build Coastguard Worker 
check_capability(&self, c: VmCap) -> bool228*bb4ee6a4SAndroid Build Coastguard Worker     fn check_capability(&self, c: VmCap) -> bool {
229*bb4ee6a4SAndroid Build Coastguard Worker         match c {
230*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::DirtyLog => false,
231*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::PvClock => false,
232*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::Protected => false,
233*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::EarlyInitCpuid => false,
234*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::BusLockDetect => false,
235*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::ReadOnlyMemoryRegion => false,
236*bb4ee6a4SAndroid Build Coastguard Worker             VmCap::MemNoncoherentDma => false,
237*bb4ee6a4SAndroid Build Coastguard Worker         }
238*bb4ee6a4SAndroid Build Coastguard Worker     }
239*bb4ee6a4SAndroid Build Coastguard Worker 
get_memory(&self) -> &GuestMemory240*bb4ee6a4SAndroid Build Coastguard Worker     fn get_memory(&self) -> &GuestMemory {
241*bb4ee6a4SAndroid Build Coastguard Worker         &self.guest_mem
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker 
add_memory_region( &mut self, guest_addr: GuestAddress, mem: Box<dyn MappedRegion>, read_only: bool, _log_dirty_pages: bool, _cache: MemCacheType, ) -> Result<MemSlot>244*bb4ee6a4SAndroid Build Coastguard Worker     fn add_memory_region(
245*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
246*bb4ee6a4SAndroid Build Coastguard Worker         guest_addr: GuestAddress,
247*bb4ee6a4SAndroid Build Coastguard Worker         mem: Box<dyn MappedRegion>,
248*bb4ee6a4SAndroid Build Coastguard Worker         read_only: bool,
249*bb4ee6a4SAndroid Build Coastguard Worker         _log_dirty_pages: bool,
250*bb4ee6a4SAndroid Build Coastguard Worker         _cache: MemCacheType,
251*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<MemSlot> {
252*bb4ee6a4SAndroid Build Coastguard Worker         let size = mem.size() as u64;
253*bb4ee6a4SAndroid Build Coastguard Worker         let end_addr = guest_addr.checked_add(size).ok_or(Error::new(EOVERFLOW))?;
254*bb4ee6a4SAndroid Build Coastguard Worker         if self.guest_mem.range_overlap(guest_addr, end_addr) {
255*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(ENOSPC));
256*bb4ee6a4SAndroid Build Coastguard Worker         }
257*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = self.mem_regions.lock();
258*bb4ee6a4SAndroid Build Coastguard Worker         let mut gaps = self.mem_slot_gaps.lock();
259*bb4ee6a4SAndroid Build Coastguard Worker         let slot = match gaps.pop() {
260*bb4ee6a4SAndroid Build Coastguard Worker             Some(gap) => gap.0,
261*bb4ee6a4SAndroid Build Coastguard Worker             None => (regions.len() + self.guest_mem.num_regions() as usize) as MemSlot,
262*bb4ee6a4SAndroid Build Coastguard Worker         };
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
265*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we check that the given guest address is valid and has no overlaps. We also
266*bb4ee6a4SAndroid Build Coastguard Worker         // know that the pointer and size are correct because the MemoryMapping interface ensures
267*bb4ee6a4SAndroid Build Coastguard Worker         // this. We take ownership of the memory mapping so that it won't be unmapped until the slot
268*bb4ee6a4SAndroid Build Coastguard Worker         // is removed.
269*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe {
270*bb4ee6a4SAndroid Build Coastguard Worker             set_user_memory_region(
271*bb4ee6a4SAndroid Build Coastguard Worker                 &self.descriptor,
272*bb4ee6a4SAndroid Build Coastguard Worker                 read_only,
273*bb4ee6a4SAndroid Build Coastguard Worker                 guest_addr.offset(),
274*bb4ee6a4SAndroid Build Coastguard Worker                 size,
275*bb4ee6a4SAndroid Build Coastguard Worker                 MemoryRegionOp::Add(mem.as_ptr() as u64),
276*bb4ee6a4SAndroid Build Coastguard Worker             )
277*bb4ee6a4SAndroid Build Coastguard Worker         };
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = res {
280*bb4ee6a4SAndroid Build Coastguard Worker             gaps.push(Reverse(slot));
281*bb4ee6a4SAndroid Build Coastguard Worker             return Err(e);
282*bb4ee6a4SAndroid Build Coastguard Worker         }
283*bb4ee6a4SAndroid Build Coastguard Worker         regions.insert(slot, (guest_addr, mem));
284*bb4ee6a4SAndroid Build Coastguard Worker         Ok(slot)
285*bb4ee6a4SAndroid Build Coastguard Worker     }
286*bb4ee6a4SAndroid Build Coastguard Worker 
msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()>287*bb4ee6a4SAndroid Build Coastguard Worker     fn msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()> {
288*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = self.mem_regions.lock();
289*bb4ee6a4SAndroid Build Coastguard Worker         let (_, mem) = regions.get_mut(&slot).ok_or(Error::new(ENOENT))?;
290*bb4ee6a4SAndroid Build Coastguard Worker 
291*bb4ee6a4SAndroid Build Coastguard Worker         mem.msync(offset, size).map_err(|err| match err {
292*bb4ee6a4SAndroid Build Coastguard Worker             MmapError::InvalidAddress => Error::new(EFAULT),
293*bb4ee6a4SAndroid Build Coastguard Worker             MmapError::NotPageAligned => Error::new(EINVAL),
294*bb4ee6a4SAndroid Build Coastguard Worker             MmapError::SystemCallFailed(e) => e,
295*bb4ee6a4SAndroid Build Coastguard Worker             _ => Error::new(EIO),
296*bb4ee6a4SAndroid Build Coastguard Worker         })
297*bb4ee6a4SAndroid Build Coastguard Worker     }
298*bb4ee6a4SAndroid Build Coastguard Worker 
remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>>299*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>> {
300*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = self.mem_regions.lock();
301*bb4ee6a4SAndroid Build Coastguard Worker 
302*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((guest_addr, mem)) = regions.get(&slot) {
303*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
304*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because the slot is checked against the list of memory slots.
305*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
306*bb4ee6a4SAndroid Build Coastguard Worker                 set_user_memory_region(
307*bb4ee6a4SAndroid Build Coastguard Worker                     &self.descriptor,
308*bb4ee6a4SAndroid Build Coastguard Worker                     false,
309*bb4ee6a4SAndroid Build Coastguard Worker                     guest_addr.offset(),
310*bb4ee6a4SAndroid Build Coastguard Worker                     mem.size() as u64,
311*bb4ee6a4SAndroid Build Coastguard Worker                     MemoryRegionOp::Remove,
312*bb4ee6a4SAndroid Build Coastguard Worker                 )?;
313*bb4ee6a4SAndroid Build Coastguard Worker             }
314*bb4ee6a4SAndroid Build Coastguard Worker             self.mem_slot_gaps.lock().push(Reverse(slot));
315*bb4ee6a4SAndroid Build Coastguard Worker             Ok(regions.remove(&slot).unwrap().1)
316*bb4ee6a4SAndroid Build Coastguard Worker         } else {
317*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::new(ENOENT))
318*bb4ee6a4SAndroid Build Coastguard Worker         }
319*bb4ee6a4SAndroid Build Coastguard Worker     }
320*bb4ee6a4SAndroid Build Coastguard Worker 
create_device(&self, _kind: DeviceKind) -> Result<SafeDescriptor>321*bb4ee6a4SAndroid Build Coastguard Worker     fn create_device(&self, _kind: DeviceKind) -> Result<SafeDescriptor> {
322*bb4ee6a4SAndroid Build Coastguard Worker         // Haxm does not support in-kernel devices
323*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(libc::ENXIO))
324*bb4ee6a4SAndroid Build Coastguard Worker     }
325*bb4ee6a4SAndroid Build Coastguard Worker 
get_dirty_log(&self, _slot: u32, _dirty_log: &mut [u8]) -> Result<()>326*bb4ee6a4SAndroid Build Coastguard Worker     fn get_dirty_log(&self, _slot: u32, _dirty_log: &mut [u8]) -> Result<()> {
327*bb4ee6a4SAndroid Build Coastguard Worker         // Haxm does not support VmCap::DirtyLog
328*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(libc::ENXIO))
329*bb4ee6a4SAndroid Build Coastguard Worker     }
330*bb4ee6a4SAndroid Build Coastguard Worker 
register_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>331*bb4ee6a4SAndroid Build Coastguard Worker     fn register_ioevent(
332*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
333*bb4ee6a4SAndroid Build Coastguard Worker         evt: &Event,
334*bb4ee6a4SAndroid Build Coastguard Worker         addr: IoEventAddress,
335*bb4ee6a4SAndroid Build Coastguard Worker         datamatch: Datamatch,
336*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
337*bb4ee6a4SAndroid Build Coastguard Worker         if datamatch != Datamatch::AnyLength {
338*bb4ee6a4SAndroid Build Coastguard Worker             error!("HAXM currently only supports Datamatch::AnyLength");
339*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(ENOTSUP));
340*bb4ee6a4SAndroid Build Coastguard Worker         }
341*bb4ee6a4SAndroid Build Coastguard Worker 
342*bb4ee6a4SAndroid Build Coastguard Worker         if self.ioevents.contains_key(&addr) {
343*bb4ee6a4SAndroid Build Coastguard Worker             error!("HAXM does not support multiple ioevents for the same address");
344*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EEXIST));
345*bb4ee6a4SAndroid Build Coastguard Worker         }
346*bb4ee6a4SAndroid Build Coastguard Worker 
347*bb4ee6a4SAndroid Build Coastguard Worker         self.ioevents.insert(addr, evt.try_clone()?);
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>352*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_ioevent(
353*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
354*bb4ee6a4SAndroid Build Coastguard Worker         evt: &Event,
355*bb4ee6a4SAndroid Build Coastguard Worker         addr: IoEventAddress,
356*bb4ee6a4SAndroid Build Coastguard Worker         datamatch: Datamatch,
357*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
358*bb4ee6a4SAndroid Build Coastguard Worker         if datamatch != Datamatch::AnyLength {
359*bb4ee6a4SAndroid Build Coastguard Worker             error!("HAXM only supports Datamatch::AnyLength");
360*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(ENOTSUP));
361*bb4ee6a4SAndroid Build Coastguard Worker         }
362*bb4ee6a4SAndroid Build Coastguard Worker 
363*bb4ee6a4SAndroid Build Coastguard Worker         match self.ioevents.get(&addr) {
364*bb4ee6a4SAndroid Build Coastguard Worker             Some(existing_evt) => {
365*bb4ee6a4SAndroid Build Coastguard Worker                 // evt should match the existing evt associated with addr
366*bb4ee6a4SAndroid Build Coastguard Worker                 if evt != existing_evt {
367*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::new(ENOENT));
368*bb4ee6a4SAndroid Build Coastguard Worker                 }
369*bb4ee6a4SAndroid Build Coastguard Worker                 self.ioevents.remove(&addr);
370*bb4ee6a4SAndroid Build Coastguard Worker             }
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker             None => {
373*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::new(ENOENT));
374*bb4ee6a4SAndroid Build Coastguard Worker             }
375*bb4ee6a4SAndroid Build Coastguard Worker         };
376*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
377*bb4ee6a4SAndroid Build Coastguard Worker     }
378*bb4ee6a4SAndroid Build Coastguard Worker 
379*bb4ee6a4SAndroid Build Coastguard Worker     /// Trigger any io events based on the memory mapped IO at `addr`.  If the hypervisor does
380*bb4ee6a4SAndroid Build Coastguard Worker     /// in-kernel IO event delivery, this is a no-op.
handle_io_events(&self, addr: IoEventAddress, _data: &[u8]) -> Result<()>381*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_io_events(&self, addr: IoEventAddress, _data: &[u8]) -> Result<()> {
382*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(evt) = self.ioevents.get(&addr) {
383*bb4ee6a4SAndroid Build Coastguard Worker             evt.signal()?;
384*bb4ee6a4SAndroid Build Coastguard Worker         }
385*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
386*bb4ee6a4SAndroid Build Coastguard Worker     }
387*bb4ee6a4SAndroid Build Coastguard Worker 
get_pvclock(&self) -> Result<ClockState>388*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pvclock(&self) -> Result<ClockState> {
389*bb4ee6a4SAndroid Build Coastguard Worker         // Haxm does not support VmCap::PvClock
390*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(libc::ENXIO))
391*bb4ee6a4SAndroid Build Coastguard Worker     }
392*bb4ee6a4SAndroid Build Coastguard Worker 
set_pvclock(&self, _state: &ClockState) -> Result<()>393*bb4ee6a4SAndroid Build Coastguard Worker     fn set_pvclock(&self, _state: &ClockState) -> Result<()> {
394*bb4ee6a4SAndroid Build Coastguard Worker         // Haxm does not support VmCap::PvClock
395*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(libc::ENXIO))
396*bb4ee6a4SAndroid Build Coastguard Worker     }
397*bb4ee6a4SAndroid Build Coastguard Worker 
add_fd_mapping( &mut self, slot: u32, offset: usize, size: usize, fd: &dyn AsRawDescriptor, fd_offset: u64, prot: Protection, ) -> Result<()>398*bb4ee6a4SAndroid Build Coastguard Worker     fn add_fd_mapping(
399*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
400*bb4ee6a4SAndroid Build Coastguard Worker         slot: u32,
401*bb4ee6a4SAndroid Build Coastguard Worker         offset: usize,
402*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
403*bb4ee6a4SAndroid Build Coastguard Worker         fd: &dyn AsRawDescriptor,
404*bb4ee6a4SAndroid Build Coastguard Worker         fd_offset: u64,
405*bb4ee6a4SAndroid Build Coastguard Worker         prot: Protection,
406*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
407*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = self.mem_regions.lock();
408*bb4ee6a4SAndroid Build Coastguard Worker         let (_, region) = regions.get_mut(&slot).ok_or(Error::new(EINVAL))?;
409*bb4ee6a4SAndroid Build Coastguard Worker 
410*bb4ee6a4SAndroid Build Coastguard Worker         match region.add_fd_mapping(offset, size, fd, fd_offset, prot) {
411*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => Ok(()),
412*bb4ee6a4SAndroid Build Coastguard Worker             Err(MmapError::SystemCallFailed(e)) => Err(e),
413*bb4ee6a4SAndroid Build Coastguard Worker             Err(_) => Err(Error::new(EIO)),
414*bb4ee6a4SAndroid Build Coastguard Worker         }
415*bb4ee6a4SAndroid Build Coastguard Worker     }
416*bb4ee6a4SAndroid Build Coastguard Worker 
remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()>417*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()> {
418*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = self.mem_regions.lock();
419*bb4ee6a4SAndroid Build Coastguard Worker         let (_, region) = regions.get_mut(&slot).ok_or(Error::new(EINVAL))?;
420*bb4ee6a4SAndroid Build Coastguard Worker 
421*bb4ee6a4SAndroid Build Coastguard Worker         match region.remove_mapping(offset, size) {
422*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => Ok(()),
423*bb4ee6a4SAndroid Build Coastguard Worker             Err(MmapError::SystemCallFailed(e)) => Err(e),
424*bb4ee6a4SAndroid Build Coastguard Worker             Err(_) => Err(Error::new(EIO)),
425*bb4ee6a4SAndroid Build Coastguard Worker         }
426*bb4ee6a4SAndroid Build Coastguard Worker     }
427*bb4ee6a4SAndroid Build Coastguard Worker 
handle_balloon_event(&mut self, _event: crate::BalloonEvent) -> Result<()>428*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_balloon_event(&mut self, _event: crate::BalloonEvent) -> Result<()> {
429*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/233773610): implement ballooning support in haxm
430*bb4ee6a4SAndroid Build Coastguard Worker         warn!("Memory ballooning attempted but not supported on haxm hypervisor");
431*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
432*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
433*bb4ee6a4SAndroid Build Coastguard Worker     }
434*bb4ee6a4SAndroid Build Coastguard Worker 
get_guest_phys_addr_bits(&self) -> u8435*bb4ee6a4SAndroid Build Coastguard Worker     fn get_guest_phys_addr_bits(&self) -> u8 {
436*bb4ee6a4SAndroid Build Coastguard Worker         // Assume the guest physical address size is the same as the host.
437*bb4ee6a4SAndroid Build Coastguard Worker         host_phys_addr_bits()
438*bb4ee6a4SAndroid Build Coastguard Worker     }
439*bb4ee6a4SAndroid Build Coastguard Worker }
440*bb4ee6a4SAndroid Build Coastguard Worker 
441*bb4ee6a4SAndroid Build Coastguard Worker impl VmX86_64 for HaxmVm {
get_hypervisor(&self) -> &dyn HypervisorX86_64442*bb4ee6a4SAndroid Build Coastguard Worker     fn get_hypervisor(&self) -> &dyn HypervisorX86_64 {
443*bb4ee6a4SAndroid Build Coastguard Worker         &self.haxm
444*bb4ee6a4SAndroid Build Coastguard Worker     }
445*bb4ee6a4SAndroid Build Coastguard Worker 
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuX86_64>>446*bb4ee6a4SAndroid Build Coastguard Worker     fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuX86_64>> {
447*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
448*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we know that our file is a VM fd and we verify the return result.
449*bb4ee6a4SAndroid Build Coastguard Worker         let fd = unsafe { ioctl_with_ref(self, HAX_VM_IOCTL_VCPU_CREATE, &(id as u32)) };
450*bb4ee6a4SAndroid Build Coastguard Worker         if fd < 0 {
451*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
452*bb4ee6a4SAndroid Build Coastguard Worker         }
453*bb4ee6a4SAndroid Build Coastguard Worker 
454*bb4ee6a4SAndroid Build Coastguard Worker         let descriptor =
455*bb4ee6a4SAndroid Build Coastguard Worker             open_haxm_vcpu_device(USE_GHAXM.load(Ordering::Relaxed), self.vm_id, id as u32)?;
456*bb4ee6a4SAndroid Build Coastguard Worker 
457*bb4ee6a4SAndroid Build Coastguard Worker         let mut tunnel_info = hax_tunnel_info::default();
458*bb4ee6a4SAndroid Build Coastguard Worker 
459*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
460*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we created tunnel_info and we check the return code for errors
461*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
462*bb4ee6a4SAndroid Build Coastguard Worker             ioctl_with_mut_ref(&descriptor, HAX_VCPU_IOCTL_SETUP_TUNNEL, &mut tunnel_info)
463*bb4ee6a4SAndroid Build Coastguard Worker         };
464*bb4ee6a4SAndroid Build Coastguard Worker 
465*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
466*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
467*bb4ee6a4SAndroid Build Coastguard Worker         }
468*bb4ee6a4SAndroid Build Coastguard Worker 
469*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(HaxmVcpu {
470*bb4ee6a4SAndroid Build Coastguard Worker             descriptor,
471*bb4ee6a4SAndroid Build Coastguard Worker             id,
472*bb4ee6a4SAndroid Build Coastguard Worker             tunnel: tunnel_info.va as *mut hax_tunnel,
473*bb4ee6a4SAndroid Build Coastguard Worker             io_buffer: tunnel_info.io_va as *mut c_void,
474*bb4ee6a4SAndroid Build Coastguard Worker         }))
475*bb4ee6a4SAndroid Build Coastguard Worker     }
476*bb4ee6a4SAndroid Build Coastguard Worker 
477*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the address of the three-page region in the VM's address space.
478*bb4ee6a4SAndroid Build Coastguard Worker     /// This function is only necessary for 16 bit guests, which we do not support for HAXM.
set_tss_addr(&self, _addr: GuestAddress) -> Result<()>479*bb4ee6a4SAndroid Build Coastguard Worker     fn set_tss_addr(&self, _addr: GuestAddress) -> Result<()> {
480*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
481*bb4ee6a4SAndroid Build Coastguard Worker     }
482*bb4ee6a4SAndroid Build Coastguard Worker 
483*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the address of a one-page region in the VM's address space.
484*bb4ee6a4SAndroid Build Coastguard Worker     /// This function is only necessary for 16 bit guests, which we do not support for HAXM.
set_identity_map_addr(&self, _addr: GuestAddress) -> Result<()>485*bb4ee6a4SAndroid Build Coastguard Worker     fn set_identity_map_addr(&self, _addr: GuestAddress) -> Result<()> {
486*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
487*bb4ee6a4SAndroid Build Coastguard Worker     }
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker 
490*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b:241252288): Enable tests disabled with dummy feature flag - enable_haxm_tests.
491*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
492*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "enable_haxm_tests")]
493*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
494*bb4ee6a4SAndroid Build Coastguard Worker     use std::time::Duration;
495*bb4ee6a4SAndroid Build Coastguard Worker 
496*bb4ee6a4SAndroid Build Coastguard Worker     use base::EventWaitResult;
497*bb4ee6a4SAndroid Build Coastguard Worker     use base::MemoryMappingBuilder;
498*bb4ee6a4SAndroid Build Coastguard Worker     use base::SharedMemory;
499*bb4ee6a4SAndroid Build Coastguard Worker 
500*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
501*bb4ee6a4SAndroid Build Coastguard Worker 
502*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_vm()503*bb4ee6a4SAndroid Build Coastguard Worker     fn create_vm() {
504*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().expect("failed to instantiate HAXM");
505*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
506*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
507*bb4ee6a4SAndroid Build Coastguard Worker         HaxmVm::new(&haxm, mem).expect("failed to create vm");
508*bb4ee6a4SAndroid Build Coastguard Worker     }
509*bb4ee6a4SAndroid Build Coastguard Worker 
510*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_vcpu()511*bb4ee6a4SAndroid Build Coastguard Worker     fn create_vcpu() {
512*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().expect("failed to instantiate HAXM");
513*bb4ee6a4SAndroid Build Coastguard Worker         let mem =
514*bb4ee6a4SAndroid Build Coastguard Worker             GuestMemory::new(&[(GuestAddress(0), 0x1000)]).expect("failed to create guest memory");
515*bb4ee6a4SAndroid Build Coastguard Worker         let vm = HaxmVm::new(&haxm, mem).expect("failed to create vm");
516*bb4ee6a4SAndroid Build Coastguard Worker         vm.create_vcpu(0).expect("failed to create vcpu");
517*bb4ee6a4SAndroid Build Coastguard Worker     }
518*bb4ee6a4SAndroid Build Coastguard Worker 
519*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_ioevent()520*bb4ee6a4SAndroid Build Coastguard Worker     fn register_ioevent() {
521*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().expect("failed to create haxm");
522*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
523*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm = HaxmVm::new(&haxm, gm).expect("failed to create vm");
524*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().expect("failed to create event");
525*bb4ee6a4SAndroid Build Coastguard Worker         let otherevt = Event::new().expect("failed to create event");
526*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(&evt, IoEventAddress::Pio(0xf4), Datamatch::AnyLength)
527*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
528*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(&evt, IoEventAddress::Mmio(0x1000), Datamatch::AnyLength)
529*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
530*bb4ee6a4SAndroid Build Coastguard Worker 
531*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(
532*bb4ee6a4SAndroid Build Coastguard Worker             &otherevt,
533*bb4ee6a4SAndroid Build Coastguard Worker             IoEventAddress::Mmio(0x1000),
534*bb4ee6a4SAndroid Build Coastguard Worker             Datamatch::AnyLength,
535*bb4ee6a4SAndroid Build Coastguard Worker         )
536*bb4ee6a4SAndroid Build Coastguard Worker         .expect_err("HAXM should not allow you to register two events for the same address");
537*bb4ee6a4SAndroid Build Coastguard Worker 
538*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(
539*bb4ee6a4SAndroid Build Coastguard Worker             &otherevt,
540*bb4ee6a4SAndroid Build Coastguard Worker             IoEventAddress::Mmio(0x1000),
541*bb4ee6a4SAndroid Build Coastguard Worker             Datamatch::U8(None),
542*bb4ee6a4SAndroid Build Coastguard Worker         )
543*bb4ee6a4SAndroid Build Coastguard Worker         .expect_err(
544*bb4ee6a4SAndroid Build Coastguard Worker             "HAXM should not allow you to register ioevents with Datamatches other than AnyLength",
545*bb4ee6a4SAndroid Build Coastguard Worker         );
546*bb4ee6a4SAndroid Build Coastguard Worker 
547*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(
548*bb4ee6a4SAndroid Build Coastguard Worker             &otherevt,
549*bb4ee6a4SAndroid Build Coastguard Worker             IoEventAddress::Mmio(0x1000),
550*bb4ee6a4SAndroid Build Coastguard Worker             Datamatch::U32(Some(0xf6)),
551*bb4ee6a4SAndroid Build Coastguard Worker         )
552*bb4ee6a4SAndroid Build Coastguard Worker         .expect_err(
553*bb4ee6a4SAndroid Build Coastguard Worker             "HAXM should not allow you to register ioevents with Datamatches other than AnyLength",
554*bb4ee6a4SAndroid Build Coastguard Worker         );
555*bb4ee6a4SAndroid Build Coastguard Worker 
556*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&otherevt, IoEventAddress::Pio(0xf4), Datamatch::AnyLength)
557*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("unregistering an unknown event should fail");
558*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&evt, IoEventAddress::Pio(0xf5), Datamatch::AnyLength)
559*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("unregistering an unknown PIO address should fail");
560*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&evt, IoEventAddress::Pio(0x1000), Datamatch::AnyLength)
561*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("unregistering an unknown PIO address should fail");
562*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&evt, IoEventAddress::Mmio(0xf4), Datamatch::AnyLength)
563*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("unregistering an unknown MMIO address should fail");
564*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&evt, IoEventAddress::Pio(0xf4), Datamatch::AnyLength)
565*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
566*bb4ee6a4SAndroid Build Coastguard Worker         vm.unregister_ioevent(&evt, IoEventAddress::Mmio(0x1000), Datamatch::AnyLength)
567*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
568*bb4ee6a4SAndroid Build Coastguard Worker     }
569*bb4ee6a4SAndroid Build Coastguard Worker 
570*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
handle_io_events()571*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_io_events() {
572*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().expect("failed to create haxm");
573*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
574*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm = HaxmVm::new(&haxm, gm).expect("failed to create vm");
575*bb4ee6a4SAndroid Build Coastguard Worker         let evt = Event::new().expect("failed to create event");
576*bb4ee6a4SAndroid Build Coastguard Worker         let evt2 = Event::new().expect("failed to create event");
577*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(&evt, IoEventAddress::Pio(0x1000), Datamatch::AnyLength)
578*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
579*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_ioevent(&evt2, IoEventAddress::Mmio(0x1000), Datamatch::AnyLength)
580*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
581*bb4ee6a4SAndroid Build Coastguard Worker 
582*bb4ee6a4SAndroid Build Coastguard Worker         // Check a pio address
583*bb4ee6a4SAndroid Build Coastguard Worker         vm.handle_io_events(IoEventAddress::Pio(0x1000), &[])
584*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to handle_io_events");
585*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(
586*bb4ee6a4SAndroid Build Coastguard Worker             evt.wait_timeout(Duration::from_millis(10))
587*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
588*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
589*bb4ee6a4SAndroid Build Coastguard Worker         );
590*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
591*bb4ee6a4SAndroid Build Coastguard Worker             evt2.wait_timeout(Duration::from_millis(10))
592*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
593*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
594*bb4ee6a4SAndroid Build Coastguard Worker         );
595*bb4ee6a4SAndroid Build Coastguard Worker         // Check an mmio address
596*bb4ee6a4SAndroid Build Coastguard Worker         vm.handle_io_events(IoEventAddress::Mmio(0x1000), &[])
597*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to handle_io_events");
598*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
599*bb4ee6a4SAndroid Build Coastguard Worker             evt.wait_timeout(Duration::from_millis(10))
600*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
601*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
602*bb4ee6a4SAndroid Build Coastguard Worker         );
603*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(
604*bb4ee6a4SAndroid Build Coastguard Worker             evt2.wait_timeout(Duration::from_millis(10))
605*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
606*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
607*bb4ee6a4SAndroid Build Coastguard Worker         );
608*bb4ee6a4SAndroid Build Coastguard Worker 
609*bb4ee6a4SAndroid Build Coastguard Worker         // Check an address that does not match any registered ioevents
610*bb4ee6a4SAndroid Build Coastguard Worker         vm.handle_io_events(IoEventAddress::Pio(0x1001), &[])
611*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to handle_io_events");
612*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
613*bb4ee6a4SAndroid Build Coastguard Worker             evt.wait_timeout(Duration::from_millis(10))
614*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
615*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
616*bb4ee6a4SAndroid Build Coastguard Worker         );
617*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
618*bb4ee6a4SAndroid Build Coastguard Worker             evt2.wait_timeout(Duration::from_millis(10))
619*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read event"),
620*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
621*bb4ee6a4SAndroid Build Coastguard Worker         );
622*bb4ee6a4SAndroid Build Coastguard Worker     }
623*bb4ee6a4SAndroid Build Coastguard Worker 
624*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
remove_memory()625*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_memory() {
626*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().unwrap();
627*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0), 0x1000)]).unwrap();
628*bb4ee6a4SAndroid Build Coastguard Worker         let mut vm = HaxmVm::new(&haxm, gm).unwrap();
629*bb4ee6a4SAndroid Build Coastguard Worker         let mem_size = 0x1000;
630*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", mem_size as u64).unwrap();
631*bb4ee6a4SAndroid Build Coastguard Worker         let mem = MemoryMappingBuilder::new(mem_size)
632*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(&shm)
633*bb4ee6a4SAndroid Build Coastguard Worker             .build()
634*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
635*bb4ee6a4SAndroid Build Coastguard Worker         let mem_ptr = mem.as_ptr();
636*bb4ee6a4SAndroid Build Coastguard Worker         let slot = vm
637*bb4ee6a4SAndroid Build Coastguard Worker             .add_memory_region(
638*bb4ee6a4SAndroid Build Coastguard Worker                 GuestAddress(0x1000),
639*bb4ee6a4SAndroid Build Coastguard Worker                 Box::new(mem),
640*bb4ee6a4SAndroid Build Coastguard Worker                 false,
641*bb4ee6a4SAndroid Build Coastguard Worker                 false,
642*bb4ee6a4SAndroid Build Coastguard Worker                 MemCacheType::CacheCoherent,
643*bb4ee6a4SAndroid Build Coastguard Worker             )
644*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
645*bb4ee6a4SAndroid Build Coastguard Worker         let removed_mem = vm.remove_memory_region(slot).unwrap();
646*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(removed_mem.size(), mem_size);
647*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(removed_mem.as_ptr(), mem_ptr);
648*bb4ee6a4SAndroid Build Coastguard Worker     }
649*bb4ee6a4SAndroid Build Coastguard Worker 
650*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
651*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_log_file()652*bb4ee6a4SAndroid Build Coastguard Worker     fn register_log_file() {
653*bb4ee6a4SAndroid Build Coastguard Worker         let haxm = Haxm::new().unwrap();
654*bb4ee6a4SAndroid Build Coastguard Worker         let gm = GuestMemory::new(&[(GuestAddress(0), 0x1000)]).unwrap();
655*bb4ee6a4SAndroid Build Coastguard Worker         let vm = HaxmVm::new(&haxm, gm).unwrap();
656*bb4ee6a4SAndroid Build Coastguard Worker 
657*bb4ee6a4SAndroid Build Coastguard Worker         if !vm.check_raw_capability(HAX_CAP_VM_LOG) {
658*bb4ee6a4SAndroid Build Coastguard Worker             return;
659*bb4ee6a4SAndroid Build Coastguard Worker         }
660*bb4ee6a4SAndroid Build Coastguard Worker 
661*bb4ee6a4SAndroid Build Coastguard Worker         let dir = tempfile::TempDir::new().unwrap();
662*bb4ee6a4SAndroid Build Coastguard Worker         let mut file_path = dir.path().to_owned();
663*bb4ee6a4SAndroid Build Coastguard Worker         file_path.push("test");
664*bb4ee6a4SAndroid Build Coastguard Worker 
665*bb4ee6a4SAndroid Build Coastguard Worker         vm.register_log_file(file_path.to_str().unwrap())
666*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to register log file");
667*bb4ee6a4SAndroid Build Coastguard Worker 
668*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu = vm.create_vcpu(0).expect("failed to create vcpu");
669*bb4ee6a4SAndroid Build Coastguard Worker 
670*bb4ee6a4SAndroid Build Coastguard Worker         // Setting cpuid will force some logs
671*bb4ee6a4SAndroid Build Coastguard Worker         let cpuid = haxm.get_supported_cpuid().unwrap();
672*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_cpuid(&cpuid).expect("failed to set cpuid");
673*bb4ee6a4SAndroid Build Coastguard Worker 
674*bb4ee6a4SAndroid Build Coastguard Worker         assert!(file_path.exists());
675*bb4ee6a4SAndroid Build Coastguard Worker     }
676*bb4ee6a4SAndroid Build Coastguard Worker }
677