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