1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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 pub mod geniezone_sys;
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Reverse;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BinaryHeap;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CString;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::offset_of;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_ulong;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::prelude::OsStrExt;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
18*bb4ee6a4SAndroid Build Coastguard Worker
19*bb4ee6a4SAndroid Build Coastguard Worker use base::errno_result;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_mut_ref;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_val;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::pagesize;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::FromRawDescriptor;
30*bb4ee6a4SAndroid Build Coastguard Worker use base::MappedRegion;
31*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
32*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
33*bb4ee6a4SAndroid Build Coastguard Worker use base::MmapError;
34*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
35*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
36*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
37*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
38*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Fdt;
39*bb4ee6a4SAndroid Build Coastguard Worker pub use geniezone_sys::*;
40*bb4ee6a4SAndroid Build Coastguard Worker use libc::open;
41*bb4ee6a4SAndroid Build Coastguard Worker use libc::EFAULT;
42*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
43*bb4ee6a4SAndroid Build Coastguard Worker use libc::EIO;
44*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOENT;
45*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOMEM;
46*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOSPC;
47*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOTSUP;
48*bb4ee6a4SAndroid Build Coastguard Worker use libc::EOVERFLOW;
49*bb4ee6a4SAndroid Build Coastguard Worker use libc::O_CLOEXEC;
50*bb4ee6a4SAndroid Build Coastguard Worker use libc::O_RDWR;
51*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
52*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
53*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
54*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::MemoryRegionPurpose;
55*bb4ee6a4SAndroid Build Coastguard Worker
56*bb4ee6a4SAndroid Build Coastguard Worker use crate::AArch64SysRegId;
57*bb4ee6a4SAndroid Build Coastguard Worker use crate::BalloonEvent;
58*bb4ee6a4SAndroid Build Coastguard Worker use crate::ClockState;
59*bb4ee6a4SAndroid Build Coastguard Worker use crate::Config;
60*bb4ee6a4SAndroid Build Coastguard Worker use crate::Datamatch;
61*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceKind;
62*bb4ee6a4SAndroid Build Coastguard Worker use crate::Hypervisor;
63*bb4ee6a4SAndroid Build Coastguard Worker use crate::HypervisorCap;
64*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoEventAddress;
65*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoOperation;
66*bb4ee6a4SAndroid Build Coastguard Worker use crate::IoParams;
67*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemCacheType;
68*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemSlot;
69*bb4ee6a4SAndroid Build Coastguard Worker use crate::PsciVersion;
70*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vcpu;
71*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuAArch64;
72*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuExit;
73*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuFeature;
74*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuRegAArch64;
75*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuSignalHandle;
76*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuSignalHandleInner;
77*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vm;
78*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmAArch64;
79*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmCap;
80*bb4ee6a4SAndroid Build Coastguard Worker use crate::PSCI_0_2;
81*bb4ee6a4SAndroid Build Coastguard Worker
82*bb4ee6a4SAndroid Build Coastguard Worker impl Geniezone {
83*bb4ee6a4SAndroid Build Coastguard Worker /// Get the size of guest physical addresses (IPA) in bits.
get_guest_phys_addr_bits(&self) -> u884*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_guest_phys_addr_bits(&self) -> u8 {
85*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
86*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know self is a real geniezone fd
87*bb4ee6a4SAndroid Build Coastguard Worker match unsafe { ioctl_with_val(self, GZVM_CHECK_EXTENSION, GZVM_CAP_ARM_VM_IPA_SIZE.into()) }
88*bb4ee6a4SAndroid Build Coastguard Worker {
89*bb4ee6a4SAndroid Build Coastguard Worker // Default physical address size is 40 bits if the extension is not supported.
90*bb4ee6a4SAndroid Build Coastguard Worker ret if ret <= 0 => 40,
91*bb4ee6a4SAndroid Build Coastguard Worker ipa => ipa as u8,
92*bb4ee6a4SAndroid Build Coastguard Worker }
93*bb4ee6a4SAndroid Build Coastguard Worker }
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker
96*bb4ee6a4SAndroid Build Coastguard Worker impl GeniezoneVm {
97*bb4ee6a4SAndroid Build Coastguard Worker /// Does platform specific initialization for the GeniezoneVm.
init_arch(&self, cfg: &Config) -> Result<()>98*bb4ee6a4SAndroid Build Coastguard Worker pub fn init_arch(&self, cfg: &Config) -> Result<()> {
99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "aarch64")]
100*bb4ee6a4SAndroid Build Coastguard Worker if cfg.mte {
101*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
102*bb4ee6a4SAndroid Build Coastguard Worker // Safe because it does not take pointer arguments.
103*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
104*bb4ee6a4SAndroid Build Coastguard Worker self.ctrl_geniezone_enable_capability(GeniezoneCap::ArmMte, &[0, 0, 0, 0, 0])
105*bb4ee6a4SAndroid Build Coastguard Worker }?;
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
108*bb4ee6a4SAndroid Build Coastguard Worker }
109*bb4ee6a4SAndroid Build Coastguard Worker
110*bb4ee6a4SAndroid Build Coastguard Worker /// Checks if a particular `VmCap` is available, or returns None if arch-independent
111*bb4ee6a4SAndroid Build Coastguard Worker /// Vm.check_capability() should handle the check.
check_capability_arch(&self, _c: VmCap) -> Option<bool>112*bb4ee6a4SAndroid Build Coastguard Worker pub fn check_capability_arch(&self, _c: VmCap) -> Option<bool> {
113*bb4ee6a4SAndroid Build Coastguard Worker None
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker
116*bb4ee6a4SAndroid Build Coastguard Worker /// Arch-specific implementation of `Vm::get_pvclock`. Always returns an error on AArch64.
get_pvclock_arch(&self) -> Result<ClockState>117*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_pvclock_arch(&self) -> Result<ClockState> {
118*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support pvclock currently
119*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support get_pvclock_arch");
120*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
121*bb4ee6a4SAndroid Build Coastguard Worker }
122*bb4ee6a4SAndroid Build Coastguard Worker
123*bb4ee6a4SAndroid Build Coastguard Worker /// Arch-specific implementation of `Vm::set_pvclock`. Always returns an error on AArch64.
set_pvclock_arch(&self, _state: &ClockState) -> Result<()>124*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_pvclock_arch(&self, _state: &ClockState) -> Result<()> {
125*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support pvclock currently
126*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support set_pvclock_arch");
127*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
128*bb4ee6a4SAndroid Build Coastguard Worker }
129*bb4ee6a4SAndroid Build Coastguard Worker
get_protected_vm_info(&self) -> Result<u64>130*bb4ee6a4SAndroid Build Coastguard Worker fn get_protected_vm_info(&self) -> Result<u64> {
131*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
132*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel won't write beyond the end of
133*bb4ee6a4SAndroid Build Coastguard Worker // the struct or keep a pointer to it.
134*bb4ee6a4SAndroid Build Coastguard Worker let cap: gzvm_enable_cap = unsafe {
135*bb4ee6a4SAndroid Build Coastguard Worker self.ctrl_geniezone_enable_capability(
136*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneCap::ArmProtectedVm,
137*bb4ee6a4SAndroid Build Coastguard Worker &[GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE as u64, 0, 0, 0, 0],
138*bb4ee6a4SAndroid Build Coastguard Worker )
139*bb4ee6a4SAndroid Build Coastguard Worker }?;
140*bb4ee6a4SAndroid Build Coastguard Worker Ok(cap.args[1])
141*bb4ee6a4SAndroid Build Coastguard Worker }
142*bb4ee6a4SAndroid Build Coastguard Worker
set_protected_vm_firmware_ipa(&self, fw_addr: GuestAddress) -> Result<()>143*bb4ee6a4SAndroid Build Coastguard Worker fn set_protected_vm_firmware_ipa(&self, fw_addr: GuestAddress) -> Result<()> {
144*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
145*bb4ee6a4SAndroid Build Coastguard Worker // Safe because none of the args are pointers.
146*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
147*bb4ee6a4SAndroid Build Coastguard Worker self.ctrl_geniezone_enable_capability(
148*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneCap::ArmProtectedVm,
149*bb4ee6a4SAndroid Build Coastguard Worker &[GZVM_CAP_ARM_PVM_SET_PVMFW_IPA as u64, fw_addr.0, 0, 0, 0],
150*bb4ee6a4SAndroid Build Coastguard Worker )
151*bb4ee6a4SAndroid Build Coastguard Worker }?;
152*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker }
155*bb4ee6a4SAndroid Build Coastguard Worker
156*bb4ee6a4SAndroid Build Coastguard Worker impl VmAArch64 for GeniezoneVm {
get_hypervisor(&self) -> &dyn Hypervisor157*bb4ee6a4SAndroid Build Coastguard Worker fn get_hypervisor(&self) -> &dyn Hypervisor {
158*bb4ee6a4SAndroid Build Coastguard Worker &self.geniezone
159*bb4ee6a4SAndroid Build Coastguard Worker }
160*bb4ee6a4SAndroid Build Coastguard Worker
load_protected_vm_firmware( &mut self, fw_addr: GuestAddress, fw_max_size: u64, ) -> Result<()>161*bb4ee6a4SAndroid Build Coastguard Worker fn load_protected_vm_firmware(
162*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
163*bb4ee6a4SAndroid Build Coastguard Worker fw_addr: GuestAddress,
164*bb4ee6a4SAndroid Build Coastguard Worker fw_max_size: u64,
165*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
166*bb4ee6a4SAndroid Build Coastguard Worker let size: u64 = self.get_protected_vm_info()?;
167*bb4ee6a4SAndroid Build Coastguard Worker if size == 0 {
168*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
169*bb4ee6a4SAndroid Build Coastguard Worker } else {
170*bb4ee6a4SAndroid Build Coastguard Worker if size > fw_max_size {
171*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(ENOMEM));
172*bb4ee6a4SAndroid Build Coastguard Worker }
173*bb4ee6a4SAndroid Build Coastguard Worker self.set_protected_vm_firmware_ipa(fw_addr)
174*bb4ee6a4SAndroid Build Coastguard Worker }
175*bb4ee6a4SAndroid Build Coastguard Worker }
176*bb4ee6a4SAndroid Build Coastguard Worker
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>177*bb4ee6a4SAndroid Build Coastguard Worker fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>> {
178*bb4ee6a4SAndroid Build Coastguard Worker Ok(Box::new(GeniezoneVm::create_vcpu(self, id)?))
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker
create_fdt(&self, _fdt: &mut Fdt, _phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()>181*bb4ee6a4SAndroid Build Coastguard Worker fn create_fdt(&self, _fdt: &mut Fdt, _phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()> {
182*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
183*bb4ee6a4SAndroid Build Coastguard Worker }
184*bb4ee6a4SAndroid Build Coastguard Worker
init_arch( &self, _payload_entry_address: GuestAddress, fdt_address: GuestAddress, fdt_size: usize, ) -> Result<()>185*bb4ee6a4SAndroid Build Coastguard Worker fn init_arch(
186*bb4ee6a4SAndroid Build Coastguard Worker &self,
187*bb4ee6a4SAndroid Build Coastguard Worker _payload_entry_address: GuestAddress,
188*bb4ee6a4SAndroid Build Coastguard Worker fdt_address: GuestAddress,
189*bb4ee6a4SAndroid Build Coastguard Worker fdt_size: usize,
190*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
191*bb4ee6a4SAndroid Build Coastguard Worker let dtb_config = gzvm_dtb_config {
192*bb4ee6a4SAndroid Build Coastguard Worker dtb_addr: fdt_address.offset(),
193*bb4ee6a4SAndroid Build Coastguard Worker dtb_size: fdt_size.try_into().unwrap(),
194*bb4ee6a4SAndroid Build Coastguard Worker };
195*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
196*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will modify exactly the size
197*bb4ee6a4SAndroid Build Coastguard Worker // of the struct.
198*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_SET_DTB_CONFIG, &dtb_config) };
199*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
200*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
201*bb4ee6a4SAndroid Build Coastguard Worker } else {
202*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker
207*bb4ee6a4SAndroid Build Coastguard Worker impl GeniezoneVcpu {
set_one_geniezone_reg_u64( &self, gzvm_reg_id: GeniezoneVcpuRegister, data: u64, ) -> Result<()>208*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_geniezone_reg_u64(
209*bb4ee6a4SAndroid Build Coastguard Worker &self,
210*bb4ee6a4SAndroid Build Coastguard Worker gzvm_reg_id: GeniezoneVcpuRegister,
211*bb4ee6a4SAndroid Build Coastguard Worker data: u64,
212*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
213*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_geniezone_reg(gzvm_reg_id, data.to_ne_bytes().as_slice())
214*bb4ee6a4SAndroid Build Coastguard Worker }
215*bb4ee6a4SAndroid Build Coastguard Worker
set_one_geniezone_reg(&self, gzvm_reg_id: GeniezoneVcpuRegister, data: &[u8]) -> Result<()>216*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_geniezone_reg(&self, gzvm_reg_id: GeniezoneVcpuRegister, data: &[u8]) -> Result<()> {
217*bb4ee6a4SAndroid Build Coastguard Worker let onereg = gzvm_one_reg {
218*bb4ee6a4SAndroid Build Coastguard Worker id: gzvm_reg_id.into(),
219*bb4ee6a4SAndroid Build Coastguard Worker addr: (data.as_ptr() as usize)
220*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
221*bb4ee6a4SAndroid Build Coastguard Worker .expect("can't represent usize as u64"),
222*bb4ee6a4SAndroid Build Coastguard Worker };
223*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
224*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
225*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
226*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_SET_ONE_REG, &onereg) };
227*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
228*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
229*bb4ee6a4SAndroid Build Coastguard Worker } else {
230*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
231*bb4ee6a4SAndroid Build Coastguard Worker }
232*bb4ee6a4SAndroid Build Coastguard Worker }
233*bb4ee6a4SAndroid Build Coastguard Worker
get_one_geniezone_reg_u64(&self, gzvm_reg_id: GeniezoneVcpuRegister) -> Result<u64>234*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_geniezone_reg_u64(&self, gzvm_reg_id: GeniezoneVcpuRegister) -> Result<u64> {
235*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes = 0u64.to_ne_bytes();
236*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_geniezone_reg(gzvm_reg_id, bytes.as_mut_slice())?;
237*bb4ee6a4SAndroid Build Coastguard Worker Ok(u64::from_ne_bytes(bytes))
238*bb4ee6a4SAndroid Build Coastguard Worker }
239*bb4ee6a4SAndroid Build Coastguard Worker
get_one_geniezone_reg( &self, gzvm_reg_id: GeniezoneVcpuRegister, data: &mut [u8], ) -> Result<()>240*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_geniezone_reg(
241*bb4ee6a4SAndroid Build Coastguard Worker &self,
242*bb4ee6a4SAndroid Build Coastguard Worker gzvm_reg_id: GeniezoneVcpuRegister,
243*bb4ee6a4SAndroid Build Coastguard Worker data: &mut [u8],
244*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
245*bb4ee6a4SAndroid Build Coastguard Worker let onereg = gzvm_one_reg {
246*bb4ee6a4SAndroid Build Coastguard Worker id: gzvm_reg_id.into(),
247*bb4ee6a4SAndroid Build Coastguard Worker addr: (data.as_mut_ptr() as usize)
248*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
249*bb4ee6a4SAndroid Build Coastguard Worker .expect("can't represent usize as u64"),
250*bb4ee6a4SAndroid Build Coastguard Worker };
251*bb4ee6a4SAndroid Build Coastguard Worker
252*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
253*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
254*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
255*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_GET_ONE_REG, &onereg) };
256*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
257*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
258*bb4ee6a4SAndroid Build Coastguard Worker } else {
259*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
260*bb4ee6a4SAndroid Build Coastguard Worker }
261*bb4ee6a4SAndroid Build Coastguard Worker }
262*bb4ee6a4SAndroid Build Coastguard Worker }
263*bb4ee6a4SAndroid Build Coastguard Worker
264*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
265*bb4ee6a4SAndroid Build Coastguard Worker /// GZVM registers as used by the `GET_ONE_REG`/`SET_ONE_REG` ioctl API
266*bb4ee6a4SAndroid Build Coastguard Worker pub enum GeniezoneVcpuRegister {
267*bb4ee6a4SAndroid Build Coastguard Worker /// General Purpose Registers X0-X30
268*bb4ee6a4SAndroid Build Coastguard Worker X(u8),
269*bb4ee6a4SAndroid Build Coastguard Worker /// Stack Pointer
270*bb4ee6a4SAndroid Build Coastguard Worker Sp,
271*bb4ee6a4SAndroid Build Coastguard Worker /// Program Counter
272*bb4ee6a4SAndroid Build Coastguard Worker Pc,
273*bb4ee6a4SAndroid Build Coastguard Worker /// Processor State
274*bb4ee6a4SAndroid Build Coastguard Worker Pstate,
275*bb4ee6a4SAndroid Build Coastguard Worker /// FP & SIMD Registers V0-V31
276*bb4ee6a4SAndroid Build Coastguard Worker V(u8),
277*bb4ee6a4SAndroid Build Coastguard Worker /// Geniezone Firmware Pseudo-Registers
278*bb4ee6a4SAndroid Build Coastguard Worker Firmware(u16),
279*bb4ee6a4SAndroid Build Coastguard Worker /// System Registers
280*bb4ee6a4SAndroid Build Coastguard Worker System(AArch64SysRegId),
281*bb4ee6a4SAndroid Build Coastguard Worker /// CCSIDR_EL1 Demultiplexed by CSSELR_EL1
282*bb4ee6a4SAndroid Build Coastguard Worker Ccsidr(u8),
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker
285*bb4ee6a4SAndroid Build Coastguard Worker /// Gives the `u64` register ID expected by the `GET_ONE_REG`/`SET_ONE_REG` ioctl API.
286*bb4ee6a4SAndroid Build Coastguard Worker impl From<GeniezoneVcpuRegister> for u64 {
from(register: GeniezoneVcpuRegister) -> Self287*bb4ee6a4SAndroid Build Coastguard Worker fn from(register: GeniezoneVcpuRegister) -> Self {
288*bb4ee6a4SAndroid Build Coastguard Worker const fn reg(size: u64, kind: u64, fields: u64) -> u64 {
289*bb4ee6a4SAndroid Build Coastguard Worker GZVM_REG_ARM64 | size | kind | fields
290*bb4ee6a4SAndroid Build Coastguard Worker }
291*bb4ee6a4SAndroid Build Coastguard Worker
292*bb4ee6a4SAndroid Build Coastguard Worker const fn gzvm_regs_reg(size: u64, offset: usize) -> u64 {
293*bb4ee6a4SAndroid Build Coastguard Worker let offset = offset / std::mem::size_of::<u32>();
294*bb4ee6a4SAndroid Build Coastguard Worker
295*bb4ee6a4SAndroid Build Coastguard Worker reg(size, GZVM_REG_ARM_CORE as u64, offset as u64)
296*bb4ee6a4SAndroid Build Coastguard Worker }
297*bb4ee6a4SAndroid Build Coastguard Worker
298*bb4ee6a4SAndroid Build Coastguard Worker const fn gzvm_reg(offset: usize) -> u64 {
299*bb4ee6a4SAndroid Build Coastguard Worker gzvm_regs_reg(GZVM_REG_SIZE_U64, offset)
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker
302*bb4ee6a4SAndroid Build Coastguard Worker fn spsr_reg(spsr_reg: u32) -> u64 {
303*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u64>() * (spsr_reg as usize);
304*bb4ee6a4SAndroid Build Coastguard Worker gzvm_reg(offset_of!(gzvm_regs, spsr) + n)
305*bb4ee6a4SAndroid Build Coastguard Worker }
306*bb4ee6a4SAndroid Build Coastguard Worker
307*bb4ee6a4SAndroid Build Coastguard Worker fn user_pt_reg(offset: usize) -> u64 {
308*bb4ee6a4SAndroid Build Coastguard Worker gzvm_regs_reg(GZVM_REG_SIZE_U64, offset_of!(gzvm_regs, regs) + offset)
309*bb4ee6a4SAndroid Build Coastguard Worker }
310*bb4ee6a4SAndroid Build Coastguard Worker
311*bb4ee6a4SAndroid Build Coastguard Worker fn user_fpsimd_state_reg(size: u64, offset: usize) -> u64 {
312*bb4ee6a4SAndroid Build Coastguard Worker gzvm_regs_reg(size, offset_of!(gzvm_regs, fp_regs) + offset)
313*bb4ee6a4SAndroid Build Coastguard Worker }
314*bb4ee6a4SAndroid Build Coastguard Worker
315*bb4ee6a4SAndroid Build Coastguard Worker const fn reg_u64(kind: u64, fields: u64) -> u64 {
316*bb4ee6a4SAndroid Build Coastguard Worker reg(GZVM_REG_SIZE_U64, kind, fields)
317*bb4ee6a4SAndroid Build Coastguard Worker }
318*bb4ee6a4SAndroid Build Coastguard Worker
319*bb4ee6a4SAndroid Build Coastguard Worker const fn demux_reg(size: u64, index: u64, value: u64) -> u64 {
320*bb4ee6a4SAndroid Build Coastguard Worker let index =
321*bb4ee6a4SAndroid Build Coastguard Worker (index << GZVM_REG_ARM_DEMUX_ID_SHIFT) & (GZVM_REG_ARM_DEMUX_ID_MASK as u64);
322*bb4ee6a4SAndroid Build Coastguard Worker let value =
323*bb4ee6a4SAndroid Build Coastguard Worker (value << GZVM_REG_ARM_DEMUX_VAL_SHIFT) & (GZVM_REG_ARM_DEMUX_VAL_MASK as u64);
324*bb4ee6a4SAndroid Build Coastguard Worker
325*bb4ee6a4SAndroid Build Coastguard Worker reg(size, GZVM_REG_ARM_DEMUX as u64, index | value)
326*bb4ee6a4SAndroid Build Coastguard Worker }
327*bb4ee6a4SAndroid Build Coastguard Worker
328*bb4ee6a4SAndroid Build Coastguard Worker match register {
329*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::X(n @ 0..=30) => {
330*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u64>() * (n as usize);
331*bb4ee6a4SAndroid Build Coastguard Worker
332*bb4ee6a4SAndroid Build Coastguard Worker user_pt_reg(offset_of!(user_pt_regs, regs) + n)
333*bb4ee6a4SAndroid Build Coastguard Worker }
334*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::X(n) => {
335*bb4ee6a4SAndroid Build Coastguard Worker unreachable!("invalid GeniezoneVcpuRegister Xn index: {n}")
336*bb4ee6a4SAndroid Build Coastguard Worker }
337*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::Sp => user_pt_reg(offset_of!(user_pt_regs, sp)),
338*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::Pc => user_pt_reg(offset_of!(user_pt_regs, pc)),
339*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::Pstate => user_pt_reg(offset_of!(user_pt_regs, pstate)),
340*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::V(n @ 0..=31) => {
341*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u128>() * (n as usize);
342*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(GZVM_REG_SIZE_U128, offset_of!(user_fpsimd_state, vregs) + n)
343*bb4ee6a4SAndroid Build Coastguard Worker }
344*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::V(n) => {
345*bb4ee6a4SAndroid Build Coastguard Worker unreachable!("invalid GeniezoneVcpuRegister Vn index: {n}")
346*bb4ee6a4SAndroid Build Coastguard Worker }
347*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::FPSR) => {
348*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(GZVM_REG_SIZE_U32, offset_of!(user_fpsimd_state, fpsr))
349*bb4ee6a4SAndroid Build Coastguard Worker }
350*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::FPCR) => {
351*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(GZVM_REG_SIZE_U32, offset_of!(user_fpsimd_state, fpcr))
352*bb4ee6a4SAndroid Build Coastguard Worker }
353*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SPSR_EL1) => spsr_reg(0),
354*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SPSR_abt) => spsr_reg(1),
355*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SPSR_und) => spsr_reg(2),
356*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SPSR_irq) => spsr_reg(3),
357*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SPSR_fiq) => spsr_reg(4),
358*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::SP_EL1) => {
359*bb4ee6a4SAndroid Build Coastguard Worker gzvm_reg(offset_of!(gzvm_regs, sp_el1))
360*bb4ee6a4SAndroid Build Coastguard Worker }
361*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(AArch64SysRegId::ELR_EL1) => {
362*bb4ee6a4SAndroid Build Coastguard Worker gzvm_reg(offset_of!(gzvm_regs, elr_el1))
363*bb4ee6a4SAndroid Build Coastguard Worker }
364*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::System(sysreg) => {
365*bb4ee6a4SAndroid Build Coastguard Worker reg_u64(GZVM_REG_ARM64_SYSREG.into(), sysreg.encoded().into())
366*bb4ee6a4SAndroid Build Coastguard Worker }
367*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::Firmware(n) => reg_u64(GZVM_REG_ARM, n.into()),
368*bb4ee6a4SAndroid Build Coastguard Worker GeniezoneVcpuRegister::Ccsidr(n) => demux_reg(GZVM_REG_SIZE_U32, 0, n.into()),
369*bb4ee6a4SAndroid Build Coastguard Worker }
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker }
372*bb4ee6a4SAndroid Build Coastguard Worker
373*bb4ee6a4SAndroid Build Coastguard Worker impl From<VcpuRegAArch64> for GeniezoneVcpuRegister {
from(reg: VcpuRegAArch64) -> Self374*bb4ee6a4SAndroid Build Coastguard Worker fn from(reg: VcpuRegAArch64) -> Self {
375*bb4ee6a4SAndroid Build Coastguard Worker match reg {
376*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::X(n @ 0..=30) => Self::X(n),
377*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::X(n) => unreachable!("invalid VcpuRegAArch64 index: {n}"),
378*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Sp => Self::Sp,
379*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Pc => Self::Pc,
380*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Pstate => Self::Pstate,
381*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::System(sysreg) => Self::System(sysreg),
382*bb4ee6a4SAndroid Build Coastguard Worker }
383*bb4ee6a4SAndroid Build Coastguard Worker }
384*bb4ee6a4SAndroid Build Coastguard Worker }
385*bb4ee6a4SAndroid Build Coastguard Worker
386*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuAArch64 for GeniezoneVcpu {
init(&self, _features: &[VcpuFeature]) -> Result<()>387*bb4ee6a4SAndroid Build Coastguard Worker fn init(&self, _features: &[VcpuFeature]) -> Result<()> {
388*bb4ee6a4SAndroid Build Coastguard Worker // Geniezone init vcpu in creation
389*bb4ee6a4SAndroid Build Coastguard Worker // Return Ok since aarch64/src/lib.rs will use this
390*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
391*bb4ee6a4SAndroid Build Coastguard Worker }
392*bb4ee6a4SAndroid Build Coastguard Worker
init_pmu(&self, _irq: u64) -> Result<()>393*bb4ee6a4SAndroid Build Coastguard Worker fn init_pmu(&self, _irq: u64) -> Result<()> {
394*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support pmu currently
395*bb4ee6a4SAndroid Build Coastguard Worker // temporary return ok since aarch64/src/lib.rs will use this
396*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
397*bb4ee6a4SAndroid Build Coastguard Worker }
398*bb4ee6a4SAndroid Build Coastguard Worker
has_pvtime_support(&self) -> bool399*bb4ee6a4SAndroid Build Coastguard Worker fn has_pvtime_support(&self) -> bool {
400*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support pvtime currently
401*bb4ee6a4SAndroid Build Coastguard Worker false
402*bb4ee6a4SAndroid Build Coastguard Worker }
403*bb4ee6a4SAndroid Build Coastguard Worker
init_pvtime(&self, _pvtime_ipa: u64) -> Result<()>404*bb4ee6a4SAndroid Build Coastguard Worker fn init_pvtime(&self, _pvtime_ipa: u64) -> Result<()> {
405*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support pvtime currently
406*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support init_pvtime");
407*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
408*bb4ee6a4SAndroid Build Coastguard Worker }
409*bb4ee6a4SAndroid Build Coastguard Worker
set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()>410*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()> {
411*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_geniezone_reg_u64(GeniezoneVcpuRegister::from(reg_id), data)
412*bb4ee6a4SAndroid Build Coastguard Worker }
413*bb4ee6a4SAndroid Build Coastguard Worker
get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64>414*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64> {
415*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_geniezone_reg_u64(GeniezoneVcpuRegister::from(reg_id))
416*bb4ee6a4SAndroid Build Coastguard Worker }
417*bb4ee6a4SAndroid Build Coastguard Worker
set_vector_reg(&self, _reg_num: u8, _data: u128) -> Result<()>418*bb4ee6a4SAndroid Build Coastguard Worker fn set_vector_reg(&self, _reg_num: u8, _data: u128) -> Result<()> {
419*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
420*bb4ee6a4SAndroid Build Coastguard Worker }
421*bb4ee6a4SAndroid Build Coastguard Worker
get_vector_reg(&self, _reg_num: u8) -> Result<u128>422*bb4ee6a4SAndroid Build Coastguard Worker fn get_vector_reg(&self, _reg_num: u8) -> Result<u128> {
423*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
424*bb4ee6a4SAndroid Build Coastguard Worker }
425*bb4ee6a4SAndroid Build Coastguard Worker
get_psci_version(&self) -> Result<PsciVersion>426*bb4ee6a4SAndroid Build Coastguard Worker fn get_psci_version(&self) -> Result<PsciVersion> {
427*bb4ee6a4SAndroid Build Coastguard Worker Ok(PSCI_0_2)
428*bb4ee6a4SAndroid Build Coastguard Worker }
429*bb4ee6a4SAndroid Build Coastguard Worker
get_max_hw_bps(&self) -> Result<usize>430*bb4ee6a4SAndroid Build Coastguard Worker fn get_max_hw_bps(&self) -> Result<usize> {
431*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support gdb currently
432*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support get_max_hw_bps");
433*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
434*bb4ee6a4SAndroid Build Coastguard Worker }
435*bb4ee6a4SAndroid Build Coastguard Worker
get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>>436*bb4ee6a4SAndroid Build Coastguard Worker fn get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>> {
437*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support get_system_regs");
438*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
439*bb4ee6a4SAndroid Build Coastguard Worker }
440*bb4ee6a4SAndroid Build Coastguard Worker
get_cache_info(&self) -> Result<BTreeMap<u8, u64>>441*bb4ee6a4SAndroid Build Coastguard Worker fn get_cache_info(&self) -> Result<BTreeMap<u8, u64>> {
442*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support get_cache_info");
443*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
444*bb4ee6a4SAndroid Build Coastguard Worker }
445*bb4ee6a4SAndroid Build Coastguard Worker
set_cache_info(&self, _cache_info: BTreeMap<u8, u64>) -> Result<()>446*bb4ee6a4SAndroid Build Coastguard Worker fn set_cache_info(&self, _cache_info: BTreeMap<u8, u64>) -> Result<()> {
447*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support set_cache_info");
448*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
449*bb4ee6a4SAndroid Build Coastguard Worker }
450*bb4ee6a4SAndroid Build Coastguard Worker
hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value>451*bb4ee6a4SAndroid Build Coastguard Worker fn hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value> {
452*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support gdb currently
453*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow::anyhow!(
454*bb4ee6a4SAndroid Build Coastguard Worker "Geniezone: not support hypervisor_specific_snapshot"
455*bb4ee6a4SAndroid Build Coastguard Worker ))
456*bb4ee6a4SAndroid Build Coastguard Worker }
457*bb4ee6a4SAndroid Build Coastguard Worker
hypervisor_specific_restore(&self, _data: serde_json::Value) -> anyhow::Result<()>458*bb4ee6a4SAndroid Build Coastguard Worker fn hypervisor_specific_restore(&self, _data: serde_json::Value) -> anyhow::Result<()> {
459*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support gdb currently
460*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow::anyhow!(
461*bb4ee6a4SAndroid Build Coastguard Worker "Geniezone: not support hypervisor_specific_restore"
462*bb4ee6a4SAndroid Build Coastguard Worker ))
463*bb4ee6a4SAndroid Build Coastguard Worker }
464*bb4ee6a4SAndroid Build Coastguard Worker
set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()>465*bb4ee6a4SAndroid Build Coastguard Worker fn set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()> {
466*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Geniezone not support gdb currently
467*bb4ee6a4SAndroid Build Coastguard Worker error!("Geniezone: not support set_guest_debug");
468*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
469*bb4ee6a4SAndroid Build Coastguard Worker }
470*bb4ee6a4SAndroid Build Coastguard Worker }
471*bb4ee6a4SAndroid Build Coastguard Worker
472*bb4ee6a4SAndroid Build Coastguard Worker // Wrapper around GZVM_SET_USER_MEMORY_REGION ioctl, which creates, modifies, or deletes a mapping
473*bb4ee6a4SAndroid Build Coastguard Worker // from guest physical to host user pages.
474*bb4ee6a4SAndroid Build Coastguard Worker //
475*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
476*bb4ee6a4SAndroid Build Coastguard Worker // Safe when the guest regions are guaranteed not to overlap.
set_user_memory_region( descriptor: &SafeDescriptor, slot: MemSlot, _read_only: bool, _log_dirty_pages: bool, guest_addr: u64, memory_size: u64, userspace_addr: *mut u8, flags: u32, ) -> Result<()>477*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn set_user_memory_region(
478*bb4ee6a4SAndroid Build Coastguard Worker descriptor: &SafeDescriptor,
479*bb4ee6a4SAndroid Build Coastguard Worker slot: MemSlot,
480*bb4ee6a4SAndroid Build Coastguard Worker _read_only: bool,
481*bb4ee6a4SAndroid Build Coastguard Worker _log_dirty_pages: bool,
482*bb4ee6a4SAndroid Build Coastguard Worker guest_addr: u64,
483*bb4ee6a4SAndroid Build Coastguard Worker memory_size: u64,
484*bb4ee6a4SAndroid Build Coastguard Worker userspace_addr: *mut u8,
485*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
486*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
487*bb4ee6a4SAndroid Build Coastguard Worker let region = gzvm_userspace_memory_region {
488*bb4ee6a4SAndroid Build Coastguard Worker slot,
489*bb4ee6a4SAndroid Build Coastguard Worker flags,
490*bb4ee6a4SAndroid Build Coastguard Worker guest_phys_addr: guest_addr,
491*bb4ee6a4SAndroid Build Coastguard Worker memory_size,
492*bb4ee6a4SAndroid Build Coastguard Worker userspace_addr: userspace_addr as u64,
493*bb4ee6a4SAndroid Build Coastguard Worker };
494*bb4ee6a4SAndroid Build Coastguard Worker
495*bb4ee6a4SAndroid Build Coastguard Worker let ret = ioctl_with_ref(descriptor, GZVM_SET_USER_MEMORY_REGION, ®ion);
496*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
497*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
498*bb4ee6a4SAndroid Build Coastguard Worker } else {
499*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
500*bb4ee6a4SAndroid Build Coastguard Worker }
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker
503*bb4ee6a4SAndroid Build Coastguard Worker /// Helper function to determine the size in bytes of a dirty log bitmap for the given memory region
504*bb4ee6a4SAndroid Build Coastguard Worker /// size.
505*bb4ee6a4SAndroid Build Coastguard Worker ///
506*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
507*bb4ee6a4SAndroid Build Coastguard Worker ///
508*bb4ee6a4SAndroid Build Coastguard Worker /// * `size` - Number of bytes in the memory region being queried.
dirty_log_bitmap_size(size: usize) -> usize509*bb4ee6a4SAndroid Build Coastguard Worker pub fn dirty_log_bitmap_size(size: usize) -> usize {
510*bb4ee6a4SAndroid Build Coastguard Worker let page_size = pagesize();
511*bb4ee6a4SAndroid Build Coastguard Worker (((size + page_size - 1) / page_size) + 7) / 8
512*bb4ee6a4SAndroid Build Coastguard Worker }
513*bb4ee6a4SAndroid Build Coastguard Worker
514*bb4ee6a4SAndroid Build Coastguard Worker pub struct Geniezone {
515*bb4ee6a4SAndroid Build Coastguard Worker geniezone: SafeDescriptor,
516*bb4ee6a4SAndroid Build Coastguard Worker }
517*bb4ee6a4SAndroid Build Coastguard Worker
518*bb4ee6a4SAndroid Build Coastguard Worker #[repr(u32)]
519*bb4ee6a4SAndroid Build Coastguard Worker pub enum GeniezoneCap {
520*bb4ee6a4SAndroid Build Coastguard Worker ArmMte,
521*bb4ee6a4SAndroid Build Coastguard Worker ArmProtectedVm = GZVM_CAP_ARM_PROTECTED_VM,
522*bb4ee6a4SAndroid Build Coastguard Worker }
523*bb4ee6a4SAndroid Build Coastguard Worker
524*bb4ee6a4SAndroid Build Coastguard Worker impl Geniezone {
new_with_path(device_path: &Path) -> Result<Geniezone>525*bb4ee6a4SAndroid Build Coastguard Worker pub fn new_with_path(device_path: &Path) -> Result<Geniezone> {
526*bb4ee6a4SAndroid Build Coastguard Worker let c_path = CString::new(device_path.as_os_str().as_bytes()).unwrap();
527*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
528*bb4ee6a4SAndroid Build Coastguard Worker // Open calls are safe because we give a nul-terminated string and verify the result.
529*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { open(c_path.as_ptr(), O_RDWR | O_CLOEXEC) };
530*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
531*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
532*bb4ee6a4SAndroid Build Coastguard Worker }
533*bb4ee6a4SAndroid Build Coastguard Worker Ok(Geniezone {
534*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
535*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we verify that ret is valid and we own the fd.
536*bb4ee6a4SAndroid Build Coastguard Worker geniezone: unsafe { SafeDescriptor::from_raw_descriptor(ret) },
537*bb4ee6a4SAndroid Build Coastguard Worker })
538*bb4ee6a4SAndroid Build Coastguard Worker }
539*bb4ee6a4SAndroid Build Coastguard Worker
540*bb4ee6a4SAndroid Build Coastguard Worker /// Opens `/dev/gzvm/` and returns a gzvm object on success.
new() -> Result<Geniezone>541*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> Result<Geniezone> {
542*bb4ee6a4SAndroid Build Coastguard Worker Geniezone::new_with_path(&PathBuf::from("/dev/gzvm"))
543*bb4ee6a4SAndroid Build Coastguard Worker }
544*bb4ee6a4SAndroid Build Coastguard Worker
545*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the size of the mmap required to use vcpu's `gzvm_vcpu_run` structure.
get_vcpu_mmap_size(&self) -> Result<usize>546*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_vcpu_mmap_size(&self) -> Result<usize> {
547*bb4ee6a4SAndroid Build Coastguard Worker // We don't use mmap, return sizeof(gzvm_vcpu_run) directly
548*bb4ee6a4SAndroid Build Coastguard Worker let res = std::mem::size_of::<gzvm_vcpu_run>();
549*bb4ee6a4SAndroid Build Coastguard Worker Ok(res)
550*bb4ee6a4SAndroid Build Coastguard Worker }
551*bb4ee6a4SAndroid Build Coastguard Worker }
552*bb4ee6a4SAndroid Build Coastguard Worker
553*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for Geniezone {
as_raw_descriptor(&self) -> RawDescriptor554*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
555*bb4ee6a4SAndroid Build Coastguard Worker self.geniezone.as_raw_descriptor()
556*bb4ee6a4SAndroid Build Coastguard Worker }
557*bb4ee6a4SAndroid Build Coastguard Worker }
558*bb4ee6a4SAndroid Build Coastguard Worker
559*bb4ee6a4SAndroid Build Coastguard Worker impl Hypervisor for Geniezone {
try_clone(&self) -> Result<Self>560*bb4ee6a4SAndroid Build Coastguard Worker fn try_clone(&self) -> Result<Self> {
561*bb4ee6a4SAndroid Build Coastguard Worker Ok(Geniezone {
562*bb4ee6a4SAndroid Build Coastguard Worker geniezone: self.geniezone.try_clone()?,
563*bb4ee6a4SAndroid Build Coastguard Worker })
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker
check_capability(&self, cap: HypervisorCap) -> bool566*bb4ee6a4SAndroid Build Coastguard Worker fn check_capability(&self, cap: HypervisorCap) -> bool {
567*bb4ee6a4SAndroid Build Coastguard Worker match cap {
568*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::UserMemory => true,
569*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::ArmPmuV3 => false,
570*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::ImmediateExit => true,
571*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::StaticSwiotlbAllocationRequired => true,
572*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::HypervisorInitializedBootContext => false,
573*bb4ee6a4SAndroid Build Coastguard Worker HypervisorCap::S390UserSigp | HypervisorCap::TscDeadlineTimer => false,
574*bb4ee6a4SAndroid Build Coastguard Worker }
575*bb4ee6a4SAndroid Build Coastguard Worker }
576*bb4ee6a4SAndroid Build Coastguard Worker }
577*bb4ee6a4SAndroid Build Coastguard Worker
578*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper around creating and using a Geniezone VM.
579*bb4ee6a4SAndroid Build Coastguard Worker pub struct GeniezoneVm {
580*bb4ee6a4SAndroid Build Coastguard Worker geniezone: Geniezone,
581*bb4ee6a4SAndroid Build Coastguard Worker vm: SafeDescriptor,
582*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: GuestMemory,
583*bb4ee6a4SAndroid Build Coastguard Worker mem_regions: Arc<Mutex<BTreeMap<MemSlot, Box<dyn MappedRegion>>>>,
584*bb4ee6a4SAndroid Build Coastguard Worker /// A min heap of MemSlot numbers that were used and then removed and can now be re-used
585*bb4ee6a4SAndroid Build Coastguard Worker mem_slot_gaps: Arc<Mutex<BinaryHeap<Reverse<MemSlot>>>>,
586*bb4ee6a4SAndroid Build Coastguard Worker }
587*bb4ee6a4SAndroid Build Coastguard Worker
588*bb4ee6a4SAndroid Build Coastguard Worker impl GeniezoneVm {
589*bb4ee6a4SAndroid Build Coastguard Worker /// Constructs a new `GeniezoneVm` using the given `Geniezone` instance.
new(geniezone: &Geniezone, guest_mem: GuestMemory, cfg: Config) -> Result<GeniezoneVm>590*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(geniezone: &Geniezone, guest_mem: GuestMemory, cfg: Config) -> Result<GeniezoneVm> {
591*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
592*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know gzvm is a real gzvm fd as this module is the only one that can make
593*bb4ee6a4SAndroid Build Coastguard Worker // gzvm objects.
594*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl(geniezone, GZVM_CREATE_VM) };
595*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
596*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
597*bb4ee6a4SAndroid Build Coastguard Worker }
598*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
599*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we verify that ret is valid and we own the fd.
600*bb4ee6a4SAndroid Build Coastguard Worker let vm_descriptor = unsafe { SafeDescriptor::from_raw_descriptor(ret) };
601*bb4ee6a4SAndroid Build Coastguard Worker for region in guest_mem.regions() {
602*bb4ee6a4SAndroid Build Coastguard Worker let flags = match region.options.purpose {
603*bb4ee6a4SAndroid Build Coastguard Worker MemoryRegionPurpose::GuestMemoryRegion => GZVM_USER_MEM_REGION_GUEST_MEM,
604*bb4ee6a4SAndroid Build Coastguard Worker MemoryRegionPurpose::ProtectedFirmwareRegion => GZVM_USER_MEM_REGION_PROTECT_FW,
605*bb4ee6a4SAndroid Build Coastguard Worker MemoryRegionPurpose::StaticSwiotlbRegion => GZVM_USER_MEM_REGION_STATIC_SWIOTLB,
606*bb4ee6a4SAndroid Build Coastguard Worker };
607*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
608*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the guest regions are guaranteed not to overlap.
609*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
610*bb4ee6a4SAndroid Build Coastguard Worker set_user_memory_region(
611*bb4ee6a4SAndroid Build Coastguard Worker &vm_descriptor,
612*bb4ee6a4SAndroid Build Coastguard Worker region.index as MemSlot,
613*bb4ee6a4SAndroid Build Coastguard Worker false,
614*bb4ee6a4SAndroid Build Coastguard Worker false,
615*bb4ee6a4SAndroid Build Coastguard Worker region.guest_addr.offset(),
616*bb4ee6a4SAndroid Build Coastguard Worker region.size as u64,
617*bb4ee6a4SAndroid Build Coastguard Worker region.host_addr as *mut u8,
618*bb4ee6a4SAndroid Build Coastguard Worker flags,
619*bb4ee6a4SAndroid Build Coastguard Worker )
620*bb4ee6a4SAndroid Build Coastguard Worker }?;
621*bb4ee6a4SAndroid Build Coastguard Worker }
622*bb4ee6a4SAndroid Build Coastguard Worker
623*bb4ee6a4SAndroid Build Coastguard Worker let vm = GeniezoneVm {
624*bb4ee6a4SAndroid Build Coastguard Worker geniezone: geniezone.try_clone()?,
625*bb4ee6a4SAndroid Build Coastguard Worker vm: vm_descriptor,
626*bb4ee6a4SAndroid Build Coastguard Worker guest_mem,
627*bb4ee6a4SAndroid Build Coastguard Worker mem_regions: Arc::new(Mutex::new(BTreeMap::new())),
628*bb4ee6a4SAndroid Build Coastguard Worker mem_slot_gaps: Arc::new(Mutex::new(BinaryHeap::new())),
629*bb4ee6a4SAndroid Build Coastguard Worker };
630*bb4ee6a4SAndroid Build Coastguard Worker vm.init_arch(&cfg)?;
631*bb4ee6a4SAndroid Build Coastguard Worker Ok(vm)
632*bb4ee6a4SAndroid Build Coastguard Worker }
633*bb4ee6a4SAndroid Build Coastguard Worker
create_vcpu(&self, id: usize) -> Result<GeniezoneVcpu>634*bb4ee6a4SAndroid Build Coastguard Worker fn create_vcpu(&self, id: usize) -> Result<GeniezoneVcpu> {
635*bb4ee6a4SAndroid Build Coastguard Worker // run is a data stucture shared with ko and geniezone
636*bb4ee6a4SAndroid Build Coastguard Worker let run_mmap_size = self.geniezone.get_vcpu_mmap_size()?;
637*bb4ee6a4SAndroid Build Coastguard Worker
638*bb4ee6a4SAndroid Build Coastguard Worker let fd =
639*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
640*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd and we verify the return result.
641*bb4ee6a4SAndroid Build Coastguard Worker unsafe { ioctl_with_val(self, GZVM_CREATE_VCPU, c_ulong::try_from(id).unwrap()) };
642*bb4ee6a4SAndroid Build Coastguard Worker
643*bb4ee6a4SAndroid Build Coastguard Worker if fd < 0 {
644*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
645*bb4ee6a4SAndroid Build Coastguard Worker }
646*bb4ee6a4SAndroid Build Coastguard Worker
647*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
648*bb4ee6a4SAndroid Build Coastguard Worker // Wrap the vcpu now in case the following ? returns early. This is safe because we verified
649*bb4ee6a4SAndroid Build Coastguard Worker // the value of the fd and we own the fd.
650*bb4ee6a4SAndroid Build Coastguard Worker let vcpu = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
651*bb4ee6a4SAndroid Build Coastguard Worker
652*bb4ee6a4SAndroid Build Coastguard Worker // Memory mapping --> Memory allocation
653*bb4ee6a4SAndroid Build Coastguard Worker let run_mmap = MemoryMappingBuilder::new(run_mmap_size)
654*bb4ee6a4SAndroid Build Coastguard Worker .build()
655*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::new(ENOSPC))?;
656*bb4ee6a4SAndroid Build Coastguard Worker
657*bb4ee6a4SAndroid Build Coastguard Worker Ok(GeniezoneVcpu {
658*bb4ee6a4SAndroid Build Coastguard Worker vm: self.vm.try_clone()?,
659*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
660*bb4ee6a4SAndroid Build Coastguard Worker id,
661*bb4ee6a4SAndroid Build Coastguard Worker run_mmap: Arc::new(run_mmap),
662*bb4ee6a4SAndroid Build Coastguard Worker })
663*bb4ee6a4SAndroid Build Coastguard Worker }
664*bb4ee6a4SAndroid Build Coastguard Worker
665*bb4ee6a4SAndroid Build Coastguard Worker /// Creates an in kernel interrupt controller.
666*bb4ee6a4SAndroid Build Coastguard Worker ///
667*bb4ee6a4SAndroid Build Coastguard Worker /// See the documentation on the GZVM_CREATE_IRQCHIP ioctl.
create_irq_chip(&self) -> Result<()>668*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_irq_chip(&self) -> Result<()> {
669*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
670*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd and we verify the return result.
671*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl(self, GZVM_CREATE_IRQCHIP) };
672*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
673*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
674*bb4ee6a4SAndroid Build Coastguard Worker } else {
675*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
676*bb4ee6a4SAndroid Build Coastguard Worker }
677*bb4ee6a4SAndroid Build Coastguard Worker }
678*bb4ee6a4SAndroid Build Coastguard Worker
679*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the level on the given irq to 1 if `active` is true, and 0 otherwise.
set_irq_line(&self, irq: u32, active: bool) -> Result<()>680*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_irq_line(&self, irq: u32, active: bool) -> Result<()> {
681*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_level = gzvm_irq_level::default();
682*bb4ee6a4SAndroid Build Coastguard Worker irq_level.__bindgen_anon_1.irq = irq;
683*bb4ee6a4SAndroid Build Coastguard Worker irq_level.level = active as u32;
684*bb4ee6a4SAndroid Build Coastguard Worker
685*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
686*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd, we know the kernel will only read the
687*bb4ee6a4SAndroid Build Coastguard Worker // correct amount of memory from our pointer, and we verify the return result.
688*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_IRQ_LINE, &irq_level) };
689*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
690*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
691*bb4ee6a4SAndroid Build Coastguard Worker } else {
692*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
693*bb4ee6a4SAndroid Build Coastguard Worker }
694*bb4ee6a4SAndroid Build Coastguard Worker }
695*bb4ee6a4SAndroid Build Coastguard Worker
696*bb4ee6a4SAndroid Build Coastguard Worker /// Registers an event that will, when signalled, trigger the `gsi` irq, and `resample_evt`
697*bb4ee6a4SAndroid Build Coastguard Worker /// ( when not None ) will be triggered when the irqchip is resampled.
register_irqfd( &self, gsi: u32, evt: &Event, resample_evt: Option<&Event>, ) -> Result<()>698*bb4ee6a4SAndroid Build Coastguard Worker pub fn register_irqfd(
699*bb4ee6a4SAndroid Build Coastguard Worker &self,
700*bb4ee6a4SAndroid Build Coastguard Worker gsi: u32,
701*bb4ee6a4SAndroid Build Coastguard Worker evt: &Event,
702*bb4ee6a4SAndroid Build Coastguard Worker resample_evt: Option<&Event>,
703*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
704*bb4ee6a4SAndroid Build Coastguard Worker let mut irqfd = gzvm_irqfd {
705*bb4ee6a4SAndroid Build Coastguard Worker fd: evt.as_raw_descriptor() as u32,
706*bb4ee6a4SAndroid Build Coastguard Worker gsi,
707*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
708*bb4ee6a4SAndroid Build Coastguard Worker };
709*bb4ee6a4SAndroid Build Coastguard Worker
710*bb4ee6a4SAndroid Build Coastguard Worker if let Some(r_evt) = resample_evt {
711*bb4ee6a4SAndroid Build Coastguard Worker irqfd.flags = GZVM_IRQFD_FLAG_RESAMPLE;
712*bb4ee6a4SAndroid Build Coastguard Worker irqfd.resamplefd = r_evt.as_raw_descriptor() as u32;
713*bb4ee6a4SAndroid Build Coastguard Worker }
714*bb4ee6a4SAndroid Build Coastguard Worker
715*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
716*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd, we know the kernel will only read the
717*bb4ee6a4SAndroid Build Coastguard Worker // correct amount of memory from our pointer, and we verify the return result.
718*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_IRQFD, &irqfd) };
719*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
720*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
721*bb4ee6a4SAndroid Build Coastguard Worker } else {
722*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
723*bb4ee6a4SAndroid Build Coastguard Worker }
724*bb4ee6a4SAndroid Build Coastguard Worker }
725*bb4ee6a4SAndroid Build Coastguard Worker
726*bb4ee6a4SAndroid Build Coastguard Worker /// Unregisters an event that was previously registered with
727*bb4ee6a4SAndroid Build Coastguard Worker /// `register_irqfd`.
728*bb4ee6a4SAndroid Build Coastguard Worker ///
729*bb4ee6a4SAndroid Build Coastguard Worker /// The `evt` and `gsi` pair must be the same as the ones passed into
730*bb4ee6a4SAndroid Build Coastguard Worker /// `register_irqfd`.
unregister_irqfd(&self, gsi: u32, evt: &Event) -> Result<()>731*bb4ee6a4SAndroid Build Coastguard Worker pub fn unregister_irqfd(&self, gsi: u32, evt: &Event) -> Result<()> {
732*bb4ee6a4SAndroid Build Coastguard Worker let irqfd = gzvm_irqfd {
733*bb4ee6a4SAndroid Build Coastguard Worker fd: evt.as_raw_descriptor() as u32,
734*bb4ee6a4SAndroid Build Coastguard Worker gsi,
735*bb4ee6a4SAndroid Build Coastguard Worker flags: GZVM_IRQFD_FLAG_DEASSIGN,
736*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
737*bb4ee6a4SAndroid Build Coastguard Worker };
738*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
739*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd, we know the kernel will only read the
740*bb4ee6a4SAndroid Build Coastguard Worker // correct amount of memory from our pointer, and we verify the return result.
741*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_IRQFD, &irqfd) };
742*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
743*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
744*bb4ee6a4SAndroid Build Coastguard Worker } else {
745*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
746*bb4ee6a4SAndroid Build Coastguard Worker }
747*bb4ee6a4SAndroid Build Coastguard Worker }
748*bb4ee6a4SAndroid Build Coastguard Worker
ioeventfd( &self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, deassign: bool, ) -> Result<()>749*bb4ee6a4SAndroid Build Coastguard Worker fn ioeventfd(
750*bb4ee6a4SAndroid Build Coastguard Worker &self,
751*bb4ee6a4SAndroid Build Coastguard Worker evt: &Event,
752*bb4ee6a4SAndroid Build Coastguard Worker addr: IoEventAddress,
753*bb4ee6a4SAndroid Build Coastguard Worker datamatch: Datamatch,
754*bb4ee6a4SAndroid Build Coastguard Worker deassign: bool,
755*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
756*bb4ee6a4SAndroid Build Coastguard Worker let (do_datamatch, datamatch_value, datamatch_len) = match datamatch {
757*bb4ee6a4SAndroid Build Coastguard Worker Datamatch::AnyLength => (false, 0, 0),
758*bb4ee6a4SAndroid Build Coastguard Worker Datamatch::U8(v) => match v {
759*bb4ee6a4SAndroid Build Coastguard Worker Some(u) => (true, u as u64, 1),
760*bb4ee6a4SAndroid Build Coastguard Worker None => (false, 0, 1),
761*bb4ee6a4SAndroid Build Coastguard Worker },
762*bb4ee6a4SAndroid Build Coastguard Worker Datamatch::U16(v) => match v {
763*bb4ee6a4SAndroid Build Coastguard Worker Some(u) => (true, u as u64, 2),
764*bb4ee6a4SAndroid Build Coastguard Worker None => (false, 0, 2),
765*bb4ee6a4SAndroid Build Coastguard Worker },
766*bb4ee6a4SAndroid Build Coastguard Worker Datamatch::U32(v) => match v {
767*bb4ee6a4SAndroid Build Coastguard Worker Some(u) => (true, u as u64, 4),
768*bb4ee6a4SAndroid Build Coastguard Worker None => (false, 0, 4),
769*bb4ee6a4SAndroid Build Coastguard Worker },
770*bb4ee6a4SAndroid Build Coastguard Worker Datamatch::U64(v) => match v {
771*bb4ee6a4SAndroid Build Coastguard Worker Some(u) => (true, u, 8),
772*bb4ee6a4SAndroid Build Coastguard Worker None => (false, 0, 8),
773*bb4ee6a4SAndroid Build Coastguard Worker },
774*bb4ee6a4SAndroid Build Coastguard Worker };
775*bb4ee6a4SAndroid Build Coastguard Worker let mut flags = 0;
776*bb4ee6a4SAndroid Build Coastguard Worker if deassign {
777*bb4ee6a4SAndroid Build Coastguard Worker flags |= 1 << gzvm_ioeventfd_flag_nr_deassign;
778*bb4ee6a4SAndroid Build Coastguard Worker }
779*bb4ee6a4SAndroid Build Coastguard Worker if do_datamatch {
780*bb4ee6a4SAndroid Build Coastguard Worker flags |= 1 << gzvm_ioeventfd_flag_nr_datamatch
781*bb4ee6a4SAndroid Build Coastguard Worker }
782*bb4ee6a4SAndroid Build Coastguard Worker if let IoEventAddress::Pio(_) = addr {
783*bb4ee6a4SAndroid Build Coastguard Worker flags |= 1 << gzvm_ioeventfd_flag_nr_pio;
784*bb4ee6a4SAndroid Build Coastguard Worker }
785*bb4ee6a4SAndroid Build Coastguard Worker let ioeventfd = gzvm_ioeventfd {
786*bb4ee6a4SAndroid Build Coastguard Worker datamatch: datamatch_value,
787*bb4ee6a4SAndroid Build Coastguard Worker len: datamatch_len,
788*bb4ee6a4SAndroid Build Coastguard Worker addr: match addr {
789*bb4ee6a4SAndroid Build Coastguard Worker IoEventAddress::Pio(p) => p,
790*bb4ee6a4SAndroid Build Coastguard Worker IoEventAddress::Mmio(m) => m,
791*bb4ee6a4SAndroid Build Coastguard Worker },
792*bb4ee6a4SAndroid Build Coastguard Worker fd: evt.as_raw_descriptor(),
793*bb4ee6a4SAndroid Build Coastguard Worker flags,
794*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
795*bb4ee6a4SAndroid Build Coastguard Worker };
796*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
797*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VM fd, we know the kernel will only read the
798*bb4ee6a4SAndroid Build Coastguard Worker // correct amount of memory from our pointer, and we verify the return result.
799*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, GZVM_IOEVENTFD, &ioeventfd) };
800*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
801*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
802*bb4ee6a4SAndroid Build Coastguard Worker } else {
803*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
804*bb4ee6a4SAndroid Build Coastguard Worker }
805*bb4ee6a4SAndroid Build Coastguard Worker }
806*bb4ee6a4SAndroid Build Coastguard Worker
807*bb4ee6a4SAndroid Build Coastguard Worker /// Checks whether a particular GZVM-specific capability is available for this VM.
check_raw_capability(&self, capability: GeniezoneCap) -> bool808*bb4ee6a4SAndroid Build Coastguard Worker fn check_raw_capability(&self, capability: GeniezoneCap) -> bool {
809*bb4ee6a4SAndroid Build Coastguard Worker let mut cap: u64 = capability as u64;
810*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
811*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a GZVM fd, and if the cap is invalid GZVM assumes
812*bb4ee6a4SAndroid Build Coastguard Worker // it's an unavailable extension and returns 0.
813*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
814*bb4ee6a4SAndroid Build Coastguard Worker ioctl_with_mut_ref(self, GZVM_CHECK_EXTENSION, &mut cap);
815*bb4ee6a4SAndroid Build Coastguard Worker }
816*bb4ee6a4SAndroid Build Coastguard Worker cap == 1
817*bb4ee6a4SAndroid Build Coastguard Worker }
818*bb4ee6a4SAndroid Build Coastguard Worker
819*bb4ee6a4SAndroid Build Coastguard Worker // Currently only used on aarch64, but works on any architecture.
820*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
821*bb4ee6a4SAndroid Build Coastguard Worker /// Enables a GZVM-specific capability for this VM, with the given arguments.
822*bb4ee6a4SAndroid Build Coastguard Worker ///
823*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
824*bb4ee6a4SAndroid Build Coastguard Worker /// This function is marked as unsafe because `args` may be interpreted as pointers for some
825*bb4ee6a4SAndroid Build Coastguard Worker /// capabilities. The caller must ensure that any pointers passed in the `args` array are
826*bb4ee6a4SAndroid Build Coastguard Worker /// allocated as the kernel expects, and that mutable pointers are owned.
ctrl_geniezone_enable_capability( &self, capability: GeniezoneCap, args: &[u64; 5], ) -> Result<gzvm_enable_cap>827*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn ctrl_geniezone_enable_capability(
828*bb4ee6a4SAndroid Build Coastguard Worker &self,
829*bb4ee6a4SAndroid Build Coastguard Worker capability: GeniezoneCap,
830*bb4ee6a4SAndroid Build Coastguard Worker args: &[u64; 5],
831*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<gzvm_enable_cap> {
832*bb4ee6a4SAndroid Build Coastguard Worker let gzvm_cap = gzvm_enable_cap {
833*bb4ee6a4SAndroid Build Coastguard Worker cap: capability as u64,
834*bb4ee6a4SAndroid Build Coastguard Worker args: *args,
835*bb4ee6a4SAndroid Build Coastguard Worker };
836*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
837*bb4ee6a4SAndroid Build Coastguard Worker // the struct, and because we assume the caller has allocated the args appropriately.
838*bb4ee6a4SAndroid Build Coastguard Worker let ret = ioctl_with_ref(self, GZVM_ENABLE_CAP, &gzvm_cap);
839*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
840*bb4ee6a4SAndroid Build Coastguard Worker Ok(gzvm_cap)
841*bb4ee6a4SAndroid Build Coastguard Worker } else {
842*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
843*bb4ee6a4SAndroid Build Coastguard Worker }
844*bb4ee6a4SAndroid Build Coastguard Worker }
845*bb4ee6a4SAndroid Build Coastguard Worker
create_geniezone_device(&self, dev: gzvm_create_device) -> Result<()>846*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_geniezone_device(&self, dev: gzvm_create_device) -> Result<()> {
847*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
848*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will modify exactly the size
849*bb4ee6a4SAndroid Build Coastguard Worker // of the struct and the return value is checked.
850*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { base::ioctl_with_ref(self, GZVM_CREATE_DEVICE, &dev) };
851*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
852*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
853*bb4ee6a4SAndroid Build Coastguard Worker } else {
854*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
855*bb4ee6a4SAndroid Build Coastguard Worker }
856*bb4ee6a4SAndroid Build Coastguard Worker }
857*bb4ee6a4SAndroid Build Coastguard Worker
handle_inflate(&mut self, guest_address: GuestAddress, size: u64) -> Result<()>858*bb4ee6a4SAndroid Build Coastguard Worker fn handle_inflate(&mut self, guest_address: GuestAddress, size: u64) -> Result<()> {
859*bb4ee6a4SAndroid Build Coastguard Worker match self.guest_mem.remove_range(guest_address, size) {
860*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => Ok(()),
861*bb4ee6a4SAndroid Build Coastguard Worker Err(vm_memory::Error::MemoryAccess(_, MmapError::SystemCallFailed(e))) => Err(e),
862*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => Err(Error::new(EIO)),
863*bb4ee6a4SAndroid Build Coastguard Worker }
864*bb4ee6a4SAndroid Build Coastguard Worker }
865*bb4ee6a4SAndroid Build Coastguard Worker
handle_deflate(&mut self, _guest_address: GuestAddress, _size: u64) -> Result<()>866*bb4ee6a4SAndroid Build Coastguard Worker fn handle_deflate(&mut self, _guest_address: GuestAddress, _size: u64) -> Result<()> {
867*bb4ee6a4SAndroid Build Coastguard Worker // No-op, when the guest attempts to access the pages again, Linux/GZVM will provide them.
868*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
869*bb4ee6a4SAndroid Build Coastguard Worker }
870*bb4ee6a4SAndroid Build Coastguard Worker }
871*bb4ee6a4SAndroid Build Coastguard Worker
872*bb4ee6a4SAndroid Build Coastguard Worker impl Vm for GeniezoneVm {
try_clone(&self) -> Result<Self>873*bb4ee6a4SAndroid Build Coastguard Worker fn try_clone(&self) -> Result<Self> {
874*bb4ee6a4SAndroid Build Coastguard Worker Ok(GeniezoneVm {
875*bb4ee6a4SAndroid Build Coastguard Worker geniezone: self.geniezone.try_clone()?,
876*bb4ee6a4SAndroid Build Coastguard Worker vm: self.vm.try_clone()?,
877*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: self.guest_mem.clone(),
878*bb4ee6a4SAndroid Build Coastguard Worker mem_regions: self.mem_regions.clone(),
879*bb4ee6a4SAndroid Build Coastguard Worker mem_slot_gaps: self.mem_slot_gaps.clone(),
880*bb4ee6a4SAndroid Build Coastguard Worker })
881*bb4ee6a4SAndroid Build Coastguard Worker }
882*bb4ee6a4SAndroid Build Coastguard Worker
check_capability(&self, c: VmCap) -> bool883*bb4ee6a4SAndroid Build Coastguard Worker fn check_capability(&self, c: VmCap) -> bool {
884*bb4ee6a4SAndroid Build Coastguard Worker if let Some(val) = self.check_capability_arch(c) {
885*bb4ee6a4SAndroid Build Coastguard Worker return val;
886*bb4ee6a4SAndroid Build Coastguard Worker }
887*bb4ee6a4SAndroid Build Coastguard Worker match c {
888*bb4ee6a4SAndroid Build Coastguard Worker VmCap::DirtyLog => true,
889*bb4ee6a4SAndroid Build Coastguard Worker VmCap::PvClock => false,
890*bb4ee6a4SAndroid Build Coastguard Worker VmCap::Protected => self.check_raw_capability(GeniezoneCap::ArmProtectedVm),
891*bb4ee6a4SAndroid Build Coastguard Worker VmCap::EarlyInitCpuid => false,
892*bb4ee6a4SAndroid Build Coastguard Worker VmCap::ReadOnlyMemoryRegion => false,
893*bb4ee6a4SAndroid Build Coastguard Worker VmCap::MemNoncoherentDma => false,
894*bb4ee6a4SAndroid Build Coastguard Worker }
895*bb4ee6a4SAndroid Build Coastguard Worker }
896*bb4ee6a4SAndroid Build Coastguard Worker
get_guest_phys_addr_bits(&self) -> u8897*bb4ee6a4SAndroid Build Coastguard Worker fn get_guest_phys_addr_bits(&self) -> u8 {
898*bb4ee6a4SAndroid Build Coastguard Worker self.geniezone.get_guest_phys_addr_bits()
899*bb4ee6a4SAndroid Build Coastguard Worker }
900*bb4ee6a4SAndroid Build Coastguard Worker
get_memory(&self) -> &GuestMemory901*bb4ee6a4SAndroid Build Coastguard Worker fn get_memory(&self) -> &GuestMemory {
902*bb4ee6a4SAndroid Build Coastguard Worker &self.guest_mem
903*bb4ee6a4SAndroid Build Coastguard Worker }
904*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>905*bb4ee6a4SAndroid Build Coastguard Worker fn add_memory_region(
906*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
907*bb4ee6a4SAndroid Build Coastguard Worker guest_addr: GuestAddress,
908*bb4ee6a4SAndroid Build Coastguard Worker mem: Box<dyn MappedRegion>,
909*bb4ee6a4SAndroid Build Coastguard Worker read_only: bool,
910*bb4ee6a4SAndroid Build Coastguard Worker log_dirty_pages: bool,
911*bb4ee6a4SAndroid Build Coastguard Worker _cache: MemCacheType,
912*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<MemSlot> {
913*bb4ee6a4SAndroid Build Coastguard Worker let pgsz = pagesize() as u64;
914*bb4ee6a4SAndroid Build Coastguard Worker // GZVM require to set the user memory region with page size aligned size. Safe to extend
915*bb4ee6a4SAndroid Build Coastguard Worker // the mem.size() to be page size aligned because the mmap will round up the size to be
916*bb4ee6a4SAndroid Build Coastguard Worker // page size aligned if it is not.
917*bb4ee6a4SAndroid Build Coastguard Worker let size = (mem.size() as u64 + pgsz - 1) / pgsz * pgsz;
918*bb4ee6a4SAndroid Build Coastguard Worker let end_addr = guest_addr
919*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(size)
920*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| Error::new(EOVERFLOW))?;
921*bb4ee6a4SAndroid Build Coastguard Worker if self.guest_mem.range_overlap(guest_addr, end_addr) {
922*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(ENOSPC));
923*bb4ee6a4SAndroid Build Coastguard Worker }
924*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = self.mem_regions.lock();
925*bb4ee6a4SAndroid Build Coastguard Worker let mut gaps = self.mem_slot_gaps.lock();
926*bb4ee6a4SAndroid Build Coastguard Worker let slot = match gaps.pop() {
927*bb4ee6a4SAndroid Build Coastguard Worker Some(gap) => gap.0,
928*bb4ee6a4SAndroid Build Coastguard Worker None => (regions.len() + self.guest_mem.num_regions() as usize) as MemSlot,
929*bb4ee6a4SAndroid Build Coastguard Worker };
930*bb4ee6a4SAndroid Build Coastguard Worker let flags = 0;
931*bb4ee6a4SAndroid Build Coastguard Worker
932*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
933*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we check that the given guest address is valid and has no overlaps. We also
934*bb4ee6a4SAndroid Build Coastguard Worker // know that the pointer and size are correct because the MemoryMapping interface ensures
935*bb4ee6a4SAndroid Build Coastguard Worker // this. We take ownership of the memory mapping so that it won't be unmapped until the slot
936*bb4ee6a4SAndroid Build Coastguard Worker // is removed.
937*bb4ee6a4SAndroid Build Coastguard Worker let res = unsafe {
938*bb4ee6a4SAndroid Build Coastguard Worker set_user_memory_region(
939*bb4ee6a4SAndroid Build Coastguard Worker &self.vm,
940*bb4ee6a4SAndroid Build Coastguard Worker slot,
941*bb4ee6a4SAndroid Build Coastguard Worker read_only,
942*bb4ee6a4SAndroid Build Coastguard Worker log_dirty_pages,
943*bb4ee6a4SAndroid Build Coastguard Worker guest_addr.offset(),
944*bb4ee6a4SAndroid Build Coastguard Worker size,
945*bb4ee6a4SAndroid Build Coastguard Worker mem.as_ptr(),
946*bb4ee6a4SAndroid Build Coastguard Worker flags,
947*bb4ee6a4SAndroid Build Coastguard Worker )
948*bb4ee6a4SAndroid Build Coastguard Worker };
949*bb4ee6a4SAndroid Build Coastguard Worker
950*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = res {
951*bb4ee6a4SAndroid Build Coastguard Worker gaps.push(Reverse(slot));
952*bb4ee6a4SAndroid Build Coastguard Worker return Err(e);
953*bb4ee6a4SAndroid Build Coastguard Worker }
954*bb4ee6a4SAndroid Build Coastguard Worker regions.insert(slot, mem);
955*bb4ee6a4SAndroid Build Coastguard Worker Ok(slot)
956*bb4ee6a4SAndroid Build Coastguard Worker }
957*bb4ee6a4SAndroid Build Coastguard Worker
msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()>958*bb4ee6a4SAndroid Build Coastguard Worker fn msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()> {
959*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = self.mem_regions.lock();
960*bb4ee6a4SAndroid Build Coastguard Worker let mem = regions.get_mut(&slot).ok_or_else(|| Error::new(ENOENT))?;
961*bb4ee6a4SAndroid Build Coastguard Worker
962*bb4ee6a4SAndroid Build Coastguard Worker mem.msync(offset, size).map_err(|err| match err {
963*bb4ee6a4SAndroid Build Coastguard Worker MmapError::InvalidAddress => Error::new(EFAULT),
964*bb4ee6a4SAndroid Build Coastguard Worker MmapError::NotPageAligned => Error::new(EINVAL),
965*bb4ee6a4SAndroid Build Coastguard Worker MmapError::SystemCallFailed(e) => e,
966*bb4ee6a4SAndroid Build Coastguard Worker _ => Error::new(EIO),
967*bb4ee6a4SAndroid Build Coastguard Worker })
968*bb4ee6a4SAndroid Build Coastguard Worker }
969*bb4ee6a4SAndroid Build Coastguard Worker
madvise_pageout_memory_region( &mut self, _slot: MemSlot, _offset: usize, _size: usize, ) -> Result<()>970*bb4ee6a4SAndroid Build Coastguard Worker fn madvise_pageout_memory_region(
971*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
972*bb4ee6a4SAndroid Build Coastguard Worker _slot: MemSlot,
973*bb4ee6a4SAndroid Build Coastguard Worker _offset: usize,
974*bb4ee6a4SAndroid Build Coastguard Worker _size: usize,
975*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
976*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENOTSUP))
977*bb4ee6a4SAndroid Build Coastguard Worker }
978*bb4ee6a4SAndroid Build Coastguard Worker
madvise_remove_memory_region( &mut self, _slot: MemSlot, _offset: usize, _size: usize, ) -> Result<()>979*bb4ee6a4SAndroid Build Coastguard Worker fn madvise_remove_memory_region(
980*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
981*bb4ee6a4SAndroid Build Coastguard Worker _slot: MemSlot,
982*bb4ee6a4SAndroid Build Coastguard Worker _offset: usize,
983*bb4ee6a4SAndroid Build Coastguard Worker _size: usize,
984*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
985*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENOTSUP))
986*bb4ee6a4SAndroid Build Coastguard Worker }
987*bb4ee6a4SAndroid Build Coastguard Worker
remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>>988*bb4ee6a4SAndroid Build Coastguard Worker fn remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>> {
989*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = self.mem_regions.lock();
990*bb4ee6a4SAndroid Build Coastguard Worker if !regions.contains_key(&slot) {
991*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(ENOENT));
992*bb4ee6a4SAndroid Build Coastguard Worker }
993*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
994*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the slot is checked against the list of memory slots.
995*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
996*bb4ee6a4SAndroid Build Coastguard Worker set_user_memory_region(&self.vm, slot, false, false, 0, 0, std::ptr::null_mut(), 0)?;
997*bb4ee6a4SAndroid Build Coastguard Worker }
998*bb4ee6a4SAndroid Build Coastguard Worker self.mem_slot_gaps.lock().push(Reverse(slot));
999*bb4ee6a4SAndroid Build Coastguard Worker // This remove will always succeed because of the contains_key check above.
1000*bb4ee6a4SAndroid Build Coastguard Worker Ok(regions.remove(&slot).unwrap())
1001*bb4ee6a4SAndroid Build Coastguard Worker }
1002*bb4ee6a4SAndroid Build Coastguard Worker
create_device(&self, _kind: DeviceKind) -> Result<SafeDescriptor>1003*bb4ee6a4SAndroid Build Coastguard Worker fn create_device(&self, _kind: DeviceKind) -> Result<SafeDescriptor> {
1004*bb4ee6a4SAndroid Build Coastguard Worker // This function should not be invoked because the vgic device is created in irqchip.
1005*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
1006*bb4ee6a4SAndroid Build Coastguard Worker }
1007*bb4ee6a4SAndroid Build Coastguard Worker
get_dirty_log(&self, _slot: MemSlot, _dirty_log: &mut [u8]) -> Result<()>1008*bb4ee6a4SAndroid Build Coastguard Worker fn get_dirty_log(&self, _slot: MemSlot, _dirty_log: &mut [u8]) -> Result<()> {
1009*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENOTSUP))
1010*bb4ee6a4SAndroid Build Coastguard Worker }
1011*bb4ee6a4SAndroid Build Coastguard Worker
register_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>1012*bb4ee6a4SAndroid Build Coastguard Worker fn register_ioevent(
1013*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1014*bb4ee6a4SAndroid Build Coastguard Worker evt: &Event,
1015*bb4ee6a4SAndroid Build Coastguard Worker addr: IoEventAddress,
1016*bb4ee6a4SAndroid Build Coastguard Worker datamatch: Datamatch,
1017*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
1018*bb4ee6a4SAndroid Build Coastguard Worker self.ioeventfd(evt, addr, datamatch, false)
1019*bb4ee6a4SAndroid Build Coastguard Worker }
1020*bb4ee6a4SAndroid Build Coastguard Worker
unregister_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>1021*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_ioevent(
1022*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1023*bb4ee6a4SAndroid Build Coastguard Worker evt: &Event,
1024*bb4ee6a4SAndroid Build Coastguard Worker addr: IoEventAddress,
1025*bb4ee6a4SAndroid Build Coastguard Worker datamatch: Datamatch,
1026*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
1027*bb4ee6a4SAndroid Build Coastguard Worker self.ioeventfd(evt, addr, datamatch, true)
1028*bb4ee6a4SAndroid Build Coastguard Worker }
1029*bb4ee6a4SAndroid Build Coastguard Worker
handle_io_events(&self, _addr: IoEventAddress, _data: &[u8]) -> Result<()>1030*bb4ee6a4SAndroid Build Coastguard Worker fn handle_io_events(&self, _addr: IoEventAddress, _data: &[u8]) -> Result<()> {
1031*bb4ee6a4SAndroid Build Coastguard Worker // GZVM delivers IO events in-kernel with ioeventfds, so this is a no-op
1032*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1033*bb4ee6a4SAndroid Build Coastguard Worker }
1034*bb4ee6a4SAndroid Build Coastguard Worker
get_pvclock(&self) -> Result<ClockState>1035*bb4ee6a4SAndroid Build Coastguard Worker fn get_pvclock(&self) -> Result<ClockState> {
1036*bb4ee6a4SAndroid Build Coastguard Worker self.get_pvclock_arch()
1037*bb4ee6a4SAndroid Build Coastguard Worker }
1038*bb4ee6a4SAndroid Build Coastguard Worker
set_pvclock(&self, state: &ClockState) -> Result<()>1039*bb4ee6a4SAndroid Build Coastguard Worker fn set_pvclock(&self, state: &ClockState) -> Result<()> {
1040*bb4ee6a4SAndroid Build Coastguard Worker self.set_pvclock_arch(state)
1041*bb4ee6a4SAndroid Build Coastguard Worker }
1042*bb4ee6a4SAndroid Build Coastguard Worker
add_fd_mapping( &mut self, slot: u32, offset: usize, size: usize, fd: &dyn AsRawDescriptor, fd_offset: u64, prot: Protection, ) -> Result<()>1043*bb4ee6a4SAndroid Build Coastguard Worker fn add_fd_mapping(
1044*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1045*bb4ee6a4SAndroid Build Coastguard Worker slot: u32,
1046*bb4ee6a4SAndroid Build Coastguard Worker offset: usize,
1047*bb4ee6a4SAndroid Build Coastguard Worker size: usize,
1048*bb4ee6a4SAndroid Build Coastguard Worker fd: &dyn AsRawDescriptor,
1049*bb4ee6a4SAndroid Build Coastguard Worker fd_offset: u64,
1050*bb4ee6a4SAndroid Build Coastguard Worker prot: Protection,
1051*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
1052*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = self.mem_regions.lock();
1053*bb4ee6a4SAndroid Build Coastguard Worker let region = regions.get_mut(&slot).ok_or_else(|| Error::new(EINVAL))?;
1054*bb4ee6a4SAndroid Build Coastguard Worker
1055*bb4ee6a4SAndroid Build Coastguard Worker match region.add_fd_mapping(offset, size, fd, fd_offset, prot) {
1056*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => Ok(()),
1057*bb4ee6a4SAndroid Build Coastguard Worker Err(MmapError::SystemCallFailed(e)) => Err(e),
1058*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => Err(Error::new(EIO)),
1059*bb4ee6a4SAndroid Build Coastguard Worker }
1060*bb4ee6a4SAndroid Build Coastguard Worker }
1061*bb4ee6a4SAndroid Build Coastguard Worker
remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()>1062*bb4ee6a4SAndroid Build Coastguard Worker fn remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()> {
1063*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = self.mem_regions.lock();
1064*bb4ee6a4SAndroid Build Coastguard Worker let region = regions.get_mut(&slot).ok_or_else(|| Error::new(EINVAL))?;
1065*bb4ee6a4SAndroid Build Coastguard Worker
1066*bb4ee6a4SAndroid Build Coastguard Worker match region.remove_mapping(offset, size) {
1067*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => Ok(()),
1068*bb4ee6a4SAndroid Build Coastguard Worker Err(MmapError::SystemCallFailed(e)) => Err(e),
1069*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => Err(Error::new(EIO)),
1070*bb4ee6a4SAndroid Build Coastguard Worker }
1071*bb4ee6a4SAndroid Build Coastguard Worker }
1072*bb4ee6a4SAndroid Build Coastguard Worker
handle_balloon_event(&mut self, event: BalloonEvent) -> Result<()>1073*bb4ee6a4SAndroid Build Coastguard Worker fn handle_balloon_event(&mut self, event: BalloonEvent) -> Result<()> {
1074*bb4ee6a4SAndroid Build Coastguard Worker match event {
1075*bb4ee6a4SAndroid Build Coastguard Worker BalloonEvent::Inflate(m) => self.handle_inflate(m.guest_address, m.size),
1076*bb4ee6a4SAndroid Build Coastguard Worker BalloonEvent::Deflate(m) => self.handle_deflate(m.guest_address, m.size),
1077*bb4ee6a4SAndroid Build Coastguard Worker BalloonEvent::BalloonTargetReached(_) => Ok(()),
1078*bb4ee6a4SAndroid Build Coastguard Worker }
1079*bb4ee6a4SAndroid Build Coastguard Worker }
1080*bb4ee6a4SAndroid Build Coastguard Worker }
1081*bb4ee6a4SAndroid Build Coastguard Worker
1082*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for GeniezoneVm {
as_raw_descriptor(&self) -> RawDescriptor1083*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
1084*bb4ee6a4SAndroid Build Coastguard Worker self.vm.as_raw_descriptor()
1085*bb4ee6a4SAndroid Build Coastguard Worker }
1086*bb4ee6a4SAndroid Build Coastguard Worker }
1087*bb4ee6a4SAndroid Build Coastguard Worker
1088*bb4ee6a4SAndroid Build Coastguard Worker struct GeniezoneVcpuSignalHandle {
1089*bb4ee6a4SAndroid Build Coastguard Worker run_mmap: Arc<MemoryMapping>,
1090*bb4ee6a4SAndroid Build Coastguard Worker }
1091*bb4ee6a4SAndroid Build Coastguard Worker
1092*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuSignalHandleInner for GeniezoneVcpuSignalHandle {
signal_immediate_exit(&self)1093*bb4ee6a4SAndroid Build Coastguard Worker fn signal_immediate_exit(&self) {
1094*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: we ensure `run_mmap` is a valid mapping of `kvm_run` at creation time, and the
1095*bb4ee6a4SAndroid Build Coastguard Worker // `Arc` ensures the mapping still exists while we hold a reference to it.
1096*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
1097*bb4ee6a4SAndroid Build Coastguard Worker let run = self.run_mmap.as_ptr() as *mut gzvm_vcpu_run;
1098*bb4ee6a4SAndroid Build Coastguard Worker (*run).immediate_exit = 1;
1099*bb4ee6a4SAndroid Build Coastguard Worker }
1100*bb4ee6a4SAndroid Build Coastguard Worker }
1101*bb4ee6a4SAndroid Build Coastguard Worker }
1102*bb4ee6a4SAndroid Build Coastguard Worker
1103*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper around using a Geniezone Vcpu.
1104*bb4ee6a4SAndroid Build Coastguard Worker pub struct GeniezoneVcpu {
1105*bb4ee6a4SAndroid Build Coastguard Worker vm: SafeDescriptor,
1106*bb4ee6a4SAndroid Build Coastguard Worker vcpu: SafeDescriptor,
1107*bb4ee6a4SAndroid Build Coastguard Worker id: usize,
1108*bb4ee6a4SAndroid Build Coastguard Worker run_mmap: Arc<MemoryMapping>,
1109*bb4ee6a4SAndroid Build Coastguard Worker }
1110*bb4ee6a4SAndroid Build Coastguard Worker
1111*bb4ee6a4SAndroid Build Coastguard Worker impl Vcpu for GeniezoneVcpu {
try_clone(&self) -> Result<Self>1112*bb4ee6a4SAndroid Build Coastguard Worker fn try_clone(&self) -> Result<Self> {
1113*bb4ee6a4SAndroid Build Coastguard Worker let vm = self.vm.try_clone()?;
1114*bb4ee6a4SAndroid Build Coastguard Worker let vcpu = self.vcpu.try_clone()?;
1115*bb4ee6a4SAndroid Build Coastguard Worker
1116*bb4ee6a4SAndroid Build Coastguard Worker Ok(GeniezoneVcpu {
1117*bb4ee6a4SAndroid Build Coastguard Worker vm,
1118*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
1119*bb4ee6a4SAndroid Build Coastguard Worker id: self.id,
1120*bb4ee6a4SAndroid Build Coastguard Worker run_mmap: self.run_mmap.clone(),
1121*bb4ee6a4SAndroid Build Coastguard Worker })
1122*bb4ee6a4SAndroid Build Coastguard Worker }
1123*bb4ee6a4SAndroid Build Coastguard Worker
as_vcpu(&self) -> &dyn Vcpu1124*bb4ee6a4SAndroid Build Coastguard Worker fn as_vcpu(&self) -> &dyn Vcpu {
1125*bb4ee6a4SAndroid Build Coastguard Worker self
1126*bb4ee6a4SAndroid Build Coastguard Worker }
1127*bb4ee6a4SAndroid Build Coastguard Worker
id(&self) -> usize1128*bb4ee6a4SAndroid Build Coastguard Worker fn id(&self) -> usize {
1129*bb4ee6a4SAndroid Build Coastguard Worker self.id
1130*bb4ee6a4SAndroid Build Coastguard Worker }
1131*bb4ee6a4SAndroid Build Coastguard Worker
1132*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::cast_ptr_alignment)]
set_immediate_exit(&self, exit: bool)1133*bb4ee6a4SAndroid Build Coastguard Worker fn set_immediate_exit(&self, exit: bool) {
1134*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment
1135*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
1136*bb4ee6a4SAndroid Build Coastguard Worker let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut gzvm_vcpu_run) };
1137*bb4ee6a4SAndroid Build Coastguard Worker run.immediate_exit = exit as u8;
1138*bb4ee6a4SAndroid Build Coastguard Worker }
1139*bb4ee6a4SAndroid Build Coastguard Worker
signal_handle(&self) -> VcpuSignalHandle1140*bb4ee6a4SAndroid Build Coastguard Worker fn signal_handle(&self) -> VcpuSignalHandle {
1141*bb4ee6a4SAndroid Build Coastguard Worker VcpuSignalHandle {
1142*bb4ee6a4SAndroid Build Coastguard Worker inner: Box::new(GeniezoneVcpuSignalHandle {
1143*bb4ee6a4SAndroid Build Coastguard Worker run_mmap: self.run_mmap.clone(),
1144*bb4ee6a4SAndroid Build Coastguard Worker }),
1145*bb4ee6a4SAndroid Build Coastguard Worker }
1146*bb4ee6a4SAndroid Build Coastguard Worker }
1147*bb4ee6a4SAndroid Build Coastguard Worker
on_suspend(&self) -> Result<()>1148*bb4ee6a4SAndroid Build Coastguard Worker fn on_suspend(&self) -> Result<()> {
1149*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1150*bb4ee6a4SAndroid Build Coastguard Worker }
1151*bb4ee6a4SAndroid Build Coastguard Worker
enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()>1152*bb4ee6a4SAndroid Build Coastguard Worker unsafe fn enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()> {
1153*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(libc::ENXIO))
1154*bb4ee6a4SAndroid Build Coastguard Worker }
1155*bb4ee6a4SAndroid Build Coastguard Worker
1156*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::cast_ptr_alignment)]
1157*bb4ee6a4SAndroid Build Coastguard Worker // The pointer is page aligned so casting to a different type is well defined, hence the clippy
1158*bb4ee6a4SAndroid Build Coastguard Worker // allow attribute.
run(&mut self) -> Result<VcpuExit>1159*bb4ee6a4SAndroid Build Coastguard Worker fn run(&mut self) -> Result<VcpuExit> {
1160*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1161*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a VCPU fd and we verify the return result.
1162*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_val(self, GZVM_RUN, self.run_mmap.as_ptr() as u64) };
1163*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
1164*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
1165*bb4ee6a4SAndroid Build Coastguard Worker }
1166*bb4ee6a4SAndroid Build Coastguard Worker
1167*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1168*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know we mapped enough memory to hold the gzvm_vcpu_run struct because the
1169*bb4ee6a4SAndroid Build Coastguard Worker // kernel told us how large it was.
1170*bb4ee6a4SAndroid Build Coastguard Worker let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut gzvm_vcpu_run) };
1171*bb4ee6a4SAndroid Build Coastguard Worker
1172*bb4ee6a4SAndroid Build Coastguard Worker match run.exit_reason {
1173*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_MMIO => Ok(VcpuExit::Mmio),
1174*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_IRQ => Ok(VcpuExit::IrqWindowOpen),
1175*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_HVC => Ok(VcpuExit::Hypercall),
1176*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_EXCEPTION => Err(Error::new(EINVAL)),
1177*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_DEBUG => Ok(VcpuExit::Debug),
1178*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_FAIL_ENTRY => {
1179*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1180*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the exit_reason (which comes from the kernel) told us which
1181*bb4ee6a4SAndroid Build Coastguard Worker // union field to use.
1182*bb4ee6a4SAndroid Build Coastguard Worker let hardware_entry_failure_reason = unsafe {
1183*bb4ee6a4SAndroid Build Coastguard Worker run.__bindgen_anon_1
1184*bb4ee6a4SAndroid Build Coastguard Worker .fail_entry
1185*bb4ee6a4SAndroid Build Coastguard Worker .hardware_entry_failure_reason
1186*bb4ee6a4SAndroid Build Coastguard Worker };
1187*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::FailEntry {
1188*bb4ee6a4SAndroid Build Coastguard Worker hardware_entry_failure_reason,
1189*bb4ee6a4SAndroid Build Coastguard Worker })
1190*bb4ee6a4SAndroid Build Coastguard Worker }
1191*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_SYSTEM_EVENT => {
1192*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1193*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the exit_reason (which comes from the kernel) told us which
1194*bb4ee6a4SAndroid Build Coastguard Worker // union field to use.
1195*bb4ee6a4SAndroid Build Coastguard Worker let event_type = unsafe { run.__bindgen_anon_1.system_event.type_ };
1196*bb4ee6a4SAndroid Build Coastguard Worker match event_type {
1197*bb4ee6a4SAndroid Build Coastguard Worker GZVM_SYSTEM_EVENT_SHUTDOWN => Ok(VcpuExit::SystemEventShutdown),
1198*bb4ee6a4SAndroid Build Coastguard Worker GZVM_SYSTEM_EVENT_RESET => Ok(VcpuExit::SystemEventReset),
1199*bb4ee6a4SAndroid Build Coastguard Worker GZVM_SYSTEM_EVENT_CRASH => Ok(VcpuExit::SystemEventCrash),
1200*bb4ee6a4SAndroid Build Coastguard Worker _ => {
1201*bb4ee6a4SAndroid Build Coastguard Worker error!("Unknown GZVM system event {}", event_type);
1202*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
1203*bb4ee6a4SAndroid Build Coastguard Worker }
1204*bb4ee6a4SAndroid Build Coastguard Worker }
1205*bb4ee6a4SAndroid Build Coastguard Worker }
1206*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_INTERNAL_ERROR => Ok(VcpuExit::InternalError),
1207*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_SHUTDOWN => Ok(VcpuExit::Shutdown(Ok(()))),
1208*bb4ee6a4SAndroid Build Coastguard Worker GZVM_EXIT_UNKNOWN => panic!("unknown gzvm exit reason\n"),
1209*bb4ee6a4SAndroid Build Coastguard Worker r => panic!("unknown gzvm exit reason: {}", r),
1210*bb4ee6a4SAndroid Build Coastguard Worker }
1211*bb4ee6a4SAndroid Build Coastguard Worker }
1212*bb4ee6a4SAndroid Build Coastguard Worker
handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()>1213*bb4ee6a4SAndroid Build Coastguard Worker fn handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()> {
1214*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1215*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know we mapped enough memory to hold the gzvm_vcpu_run struct because the
1216*bb4ee6a4SAndroid Build Coastguard Worker // kernel told us how large it was. The pointer is page aligned so casting to a different
1217*bb4ee6a4SAndroid Build Coastguard Worker // type is well defined, hence the clippy allow attribute.
1218*bb4ee6a4SAndroid Build Coastguard Worker let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut gzvm_vcpu_run) };
1219*bb4ee6a4SAndroid Build Coastguard Worker
1220*bb4ee6a4SAndroid Build Coastguard Worker // Verify that the handler is called in the right context.
1221*bb4ee6a4SAndroid Build Coastguard Worker assert!(run.exit_reason == GZVM_EXIT_MMIO);
1222*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1223*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the exit_reason (which comes from the kernel) told us which
1224*bb4ee6a4SAndroid Build Coastguard Worker // union field to use.
1225*bb4ee6a4SAndroid Build Coastguard Worker let mmio = unsafe { &mut run.__bindgen_anon_1.mmio };
1226*bb4ee6a4SAndroid Build Coastguard Worker let address = mmio.phys_addr;
1227*bb4ee6a4SAndroid Build Coastguard Worker let data = &mut mmio.data[..mmio.size as usize];
1228*bb4ee6a4SAndroid Build Coastguard Worker
1229*bb4ee6a4SAndroid Build Coastguard Worker if mmio.is_write != 0 {
1230*bb4ee6a4SAndroid Build Coastguard Worker handle_fn(IoParams {
1231*bb4ee6a4SAndroid Build Coastguard Worker address,
1232*bb4ee6a4SAndroid Build Coastguard Worker operation: IoOperation::Write(data),
1233*bb4ee6a4SAndroid Build Coastguard Worker })
1234*bb4ee6a4SAndroid Build Coastguard Worker } else {
1235*bb4ee6a4SAndroid Build Coastguard Worker handle_fn(IoParams {
1236*bb4ee6a4SAndroid Build Coastguard Worker address,
1237*bb4ee6a4SAndroid Build Coastguard Worker operation: IoOperation::Read(data),
1238*bb4ee6a4SAndroid Build Coastguard Worker })
1239*bb4ee6a4SAndroid Build Coastguard Worker }
1240*bb4ee6a4SAndroid Build Coastguard Worker }
1241*bb4ee6a4SAndroid Build Coastguard Worker
handle_io(&self, _handle_fn: &mut dyn FnMut(IoParams)) -> Result<()>1242*bb4ee6a4SAndroid Build Coastguard Worker fn handle_io(&self, _handle_fn: &mut dyn FnMut(IoParams)) -> Result<()> {
1243*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
1244*bb4ee6a4SAndroid Build Coastguard Worker }
1245*bb4ee6a4SAndroid Build Coastguard Worker }
1246*bb4ee6a4SAndroid Build Coastguard Worker
1247*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for GeniezoneVcpu {
as_raw_descriptor(&self) -> RawDescriptor1248*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
1249*bb4ee6a4SAndroid Build Coastguard Worker self.vcpu.as_raw_descriptor()
1250*bb4ee6a4SAndroid Build Coastguard Worker }
1251*bb4ee6a4SAndroid Build Coastguard Worker }
1252