1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 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 // TODO(b:240716507): There is huge chunk for code which depends on haxm, whpx or gvm to be enabled 6*bb4ee6a4SAndroid Build Coastguard Worker // but isn't marked so. Remove this when we do so. 7*bb4ee6a4SAndroid Build Coastguard Worker #![allow(dead_code, unused_imports, unused_variables, unreachable_code)] 8*bb4ee6a4SAndroid Build Coastguard Worker 9*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod control_server; 10*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod irq_wait; 11*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod main; 12*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(feature = "crash-report"))] 13*bb4ee6a4SAndroid Build Coastguard Worker mod panic_hook; 14*bb4ee6a4SAndroid Build Coastguard Worker 15*bb4ee6a4SAndroid Build Coastguard Worker mod generic; 16*bb4ee6a4SAndroid Build Coastguard Worker use generic as product; 17*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod run_vcpu; 18*bb4ee6a4SAndroid Build Coastguard Worker 19*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 20*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid; 21*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 22*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid_count; 23*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Reverse; 24*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap; 25*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::HashMap; 26*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File; 27*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions; 28*bb4ee6a4SAndroid Build Coastguard Worker use std::io::stdin; 29*bb4ee6a4SAndroid Build Coastguard Worker use std::iter; 30*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 31*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::fs::OpenOptionsExt; 32*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf; 33*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc; 34*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 35*bb4ee6a4SAndroid Build Coastguard Worker 36*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 37*bb4ee6a4SAndroid Build Coastguard Worker use aarch64::AArch64 as Arch; 38*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::sdt::SDT; 39*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow; 40*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail; 41*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context; 42*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result; 43*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuConfigArch; 44*bb4ee6a4SAndroid Build Coastguard Worker use arch::DtbOverlay; 45*bb4ee6a4SAndroid Build Coastguard Worker use arch::IrqChipArch; 46*bb4ee6a4SAndroid Build Coastguard Worker use arch::LinuxArch; 47*bb4ee6a4SAndroid Build Coastguard Worker use arch::RunnableLinuxVm; 48*bb4ee6a4SAndroid Build Coastguard Worker use arch::VcpuArch; 49*bb4ee6a4SAndroid Build Coastguard Worker use arch::VirtioDeviceStub; 50*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmArch; 51*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmComponents; 52*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmImage; 53*bb4ee6a4SAndroid Build Coastguard Worker use base::enable_high_res_timers; 54*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 55*bb4ee6a4SAndroid Build Coastguard Worker use base::info; 56*bb4ee6a4SAndroid Build Coastguard Worker use base::open_file_or_duplicate; 57*bb4ee6a4SAndroid Build Coastguard Worker use base::warn; 58*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 59*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 60*bb4ee6a4SAndroid Build Coastguard Worker use base::BlockingMode; 61*bb4ee6a4SAndroid Build Coastguard Worker use base::CloseNotifier; 62*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 63*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken; 64*bb4ee6a4SAndroid Build Coastguard Worker use base::EventType; 65*bb4ee6a4SAndroid Build Coastguard Worker use base::FlushOnDropTube; 66*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 67*bb4ee6a4SAndroid Build Coastguard Worker use base::FramingMode; 68*bb4ee6a4SAndroid Build Coastguard Worker use base::FromRawDescriptor; 69*bb4ee6a4SAndroid Build Coastguard Worker use base::ProtoTube; 70*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 71*bb4ee6a4SAndroid Build Coastguard Worker use base::ReadNotifier; 72*bb4ee6a4SAndroid Build Coastguard Worker use base::RecvTube; 73*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube; 74*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 75*bb4ee6a4SAndroid Build Coastguard Worker use base::StreamChannel; 76*bb4ee6a4SAndroid Build Coastguard Worker use base::Terminal; 77*bb4ee6a4SAndroid Build Coastguard Worker use base::TriggeredEvent; 78*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube; 79*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError; 80*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType; 81*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext; 82*bb4ee6a4SAndroid Build Coastguard Worker use broker_ipc::common_child_setup; 83*bb4ee6a4SAndroid Build Coastguard Worker use broker_ipc::CommonChildStartupArgs; 84*bb4ee6a4SAndroid Build Coastguard Worker use control_server::ControlServer; 85*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::Exit; 86*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::ExitContext; 87*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::ExitContextAnyhow; 88*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::ExitContextOption; 89*bb4ee6a4SAndroid Build Coastguard Worker use devices::create_devices_worker_thread; 90*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialHardware; 91*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialParameters; 92*bb4ee6a4SAndroid Build Coastguard Worker use devices::tsc::get_tsc_sync_mitigations; 93*bb4ee6a4SAndroid Build Coastguard Worker use devices::tsc::standard_deviation; 94*bb4ee6a4SAndroid Build Coastguard Worker use devices::tsc::TscSyncMitigations; 95*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio; 96*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::block::DiskOption; 97*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 98*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::snd::common_backend::VirtioSnd; 99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 100*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::snd::parameters::Parameters as SndParameters; 101*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 102*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::gpu::sys::windows::GpuVmmConfig; 103*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 104*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::gpu::sys::windows::InputEventSplitConfig; 105*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 106*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::gpu::sys::windows::InputEventVmmConfig; 107*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 108*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::gpu::sys::windows::product::GpuBackendConfig as GpuBackendConfigProduct; 109*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 110*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::gpu::sys::windows::run_gpu_device_worker; 111*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 112*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::snd::sys::windows::product::SndBackendConfig as SndBackendConfigProduct; 113*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 114*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::snd::sys::windows::run_snd_device_worker; 115*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 116*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::snd::sys::windows::SndSplitConfig; 117*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 118*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::BalloonFeatures; 119*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::Console; 120*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 121*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::GpuParameters; 122*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusDeviceObj; 123*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusResumeDevice; 124*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 125*bb4ee6a4SAndroid Build Coastguard Worker use devices::GvmIrqChip; 126*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 127*bb4ee6a4SAndroid Build Coastguard Worker use devices::IrqChip; 128*bb4ee6a4SAndroid Build Coastguard Worker use devices::UserspaceIrqChip; 129*bb4ee6a4SAndroid Build Coastguard Worker use devices::VcpuRunState; 130*bb4ee6a4SAndroid Build Coastguard Worker use devices::VirtioPciDevice; 131*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 132*bb4ee6a4SAndroid Build Coastguard Worker use devices::WhpxSplitIrqChip; 133*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 134*bb4ee6a4SAndroid Build Coastguard Worker use gpu_display::EventDevice; 135*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 136*bb4ee6a4SAndroid Build Coastguard Worker use gpu_display::WindowProcedureThread; 137*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 138*bb4ee6a4SAndroid Build Coastguard Worker use gpu_display::WindowProcedureThreadBuilder; 139*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 140*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::gvm::Gvm; 141*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 142*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::gvm::GvmVcpu; 143*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 144*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::gvm::GvmVersion; 145*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 146*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::gvm::GvmVm; 147*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 148*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::get_use_ghaxm; 149*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 150*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::set_use_ghaxm; 151*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 152*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::Haxm; 153*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 154*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::HaxmVcpu; 155*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 156*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::HaxmVm; 157*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 158*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::Whpx; 159*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 160*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxFeature; 161*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 162*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxVcpu; 163*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 164*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxVm; 165*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Hypervisor; 166*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 167*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorCap; 168*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 169*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorX86_64; 170*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType; 171*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm; 172*bb4ee6a4SAndroid Build Coastguard Worker use irq_wait::IrqWaitWorker; 173*bb4ee6a4SAndroid Build Coastguard Worker use jail::FakeMinijailStub as Minijail; 174*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(feature = "crash-report"))] 175*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use panic_hook::set_panic_hook; 176*bb4ee6a4SAndroid Build Coastguard Worker use product::create_snd_mute_tube_pair; 177*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(feature = "haxm", feature = "gvm", feature = "whpx"))] 178*bb4ee6a4SAndroid Build Coastguard Worker use product::create_snd_state_tube; 179*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 180*bb4ee6a4SAndroid Build Coastguard Worker use product::handle_pvclock_request; 181*bb4ee6a4SAndroid Build Coastguard Worker use product::merge_session_invariants; 182*bb4ee6a4SAndroid Build Coastguard Worker use product::run_ime_thread; 183*bb4ee6a4SAndroid Build Coastguard Worker use product::set_package_name; 184*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use product::setup_metrics_reporting; 185*bb4ee6a4SAndroid Build Coastguard Worker use product::start_service_ipc_listener; 186*bb4ee6a4SAndroid Build Coastguard Worker use product::RunControlArgs; 187*bb4ee6a4SAndroid Build Coastguard Worker use product::ServiceVmState; 188*bb4ee6a4SAndroid Build Coastguard Worker use product::Token; 189*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator; 190*bb4ee6a4SAndroid Build Coastguard Worker use run_vcpu::run_all_vcpus; 191*bb4ee6a4SAndroid Build Coastguard Worker use run_vcpu::VcpuRunMode; 192*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaGralloc; 193*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaGrallocBackendFlags; 194*bb4ee6a4SAndroid Build Coastguard Worker use smallvec::SmallVec; 195*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex; 196*bb4ee6a4SAndroid Build Coastguard Worker use tube_transporter::TubeToken; 197*bb4ee6a4SAndroid Build Coastguard Worker use tube_transporter::TubeTransporterReader; 198*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::api::VmMemoryClient; 199*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 200*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BalloonControlCommand; 201*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 202*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BalloonTube; 203*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::DeviceControlCommand; 204*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::InitialAudioSessionState; 205*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::IrqHandlerRequest; 206*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::PvClockCommand; 207*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VcpuControl; 208*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemoryRegionState; 209*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemoryRequest; 210*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRequest; 211*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmResponse; 212*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRunMode; 213*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress; 214*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory; 215*bb4ee6a4SAndroid Build Coastguard Worker use vmm_vhost::Connection; 216*bb4ee6a4SAndroid Build Coastguard Worker use vmm_vhost::FrontendReq; 217*bb4ee6a4SAndroid Build Coastguard Worker use win_util::ProcessType; 218*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 219*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::cpuid::adjust_cpuid; 220*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 221*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::cpuid::CpuIdContext; 222*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 223*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::X8664arch as Arch; 224*bb4ee6a4SAndroid Build Coastguard Worker 225*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::Config; 226*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::Executable; 227*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::InputDeviceOption; 228*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(feature = "gvm", feature = "whpx"))] 229*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::IrqChipKind; 230*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 231*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::TouchDeviceOption; 232*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::DEFAULT_TOUCH_DEVICE_HEIGHT; 233*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::config::DEFAULT_TOUCH_DEVICE_WIDTH; 234*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::sys::config::HypervisorKind; 235*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::sys::windows::broker::BrokerTubes; 236*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] 237*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::sys::windows::stats::StatisticsCollector; 238*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 239*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use crate::sys::windows::product::get_gpu_product_configs; 240*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 241*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use crate::sys::windows::product::get_snd_product_configs; 242*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 243*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use crate::sys::windows::product::get_window_procedure_thread_product_configs; 244*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::product::log_descriptor; 245*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 246*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use crate::sys::windows::product::num_input_sound_devices; 247*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 248*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use crate::sys::windows::product::num_input_sound_streams; 249*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::product::spawn_anti_tamper_thread; 250*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::product::MetricEventType; 251*bb4ee6a4SAndroid Build Coastguard Worker 252*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_GUEST_CID: u64 = 3; 253*bb4ee6a4SAndroid Build Coastguard Worker 254*bb4ee6a4SAndroid Build Coastguard Worker // by default, if enabled, the balloon WS features will use 4 bins. 255*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_BALLOON_WS_DEFAULT_NUM_BINS: u8 = 4; 256*bb4ee6a4SAndroid Build Coastguard Worker 257*bb4ee6a4SAndroid Build Coastguard Worker enum TaggedControlTube { 258*bb4ee6a4SAndroid Build Coastguard Worker Vm(FlushOnDropTube), 259*bb4ee6a4SAndroid Build Coastguard Worker Product(product::TaggedControlTube), 260*bb4ee6a4SAndroid Build Coastguard Worker } 261*bb4ee6a4SAndroid Build Coastguard Worker 262*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for TaggedControlTube { 263*bb4ee6a4SAndroid Build Coastguard Worker fn get_read_notifier(&self) -> &dyn AsRawDescriptor { 264*bb4ee6a4SAndroid Build Coastguard Worker match self { 265*bb4ee6a4SAndroid Build Coastguard Worker Self::Vm(tube) => tube.0.get_read_notifier(), 266*bb4ee6a4SAndroid Build Coastguard Worker Self::Product(tube) => tube.get_read_notifier(), 267*bb4ee6a4SAndroid Build Coastguard Worker } 268*bb4ee6a4SAndroid Build Coastguard Worker } 269*bb4ee6a4SAndroid Build Coastguard Worker } 270*bb4ee6a4SAndroid Build Coastguard Worker 271*bb4ee6a4SAndroid Build Coastguard Worker impl CloseNotifier for TaggedControlTube { 272*bb4ee6a4SAndroid Build Coastguard Worker fn get_close_notifier(&self) -> &dyn AsRawDescriptor { 273*bb4ee6a4SAndroid Build Coastguard Worker match self { 274*bb4ee6a4SAndroid Build Coastguard Worker Self::Vm(tube) => tube.0.get_close_notifier(), 275*bb4ee6a4SAndroid Build Coastguard Worker Self::Product(tube) => tube.get_close_notifier(), 276*bb4ee6a4SAndroid Build Coastguard Worker } 277*bb4ee6a4SAndroid Build Coastguard Worker } 278*bb4ee6a4SAndroid Build Coastguard Worker } 279*bb4ee6a4SAndroid Build Coastguard Worker 280*bb4ee6a4SAndroid Build Coastguard Worker pub enum ExitState { 281*bb4ee6a4SAndroid Build Coastguard Worker Reset, 282*bb4ee6a4SAndroid Build Coastguard Worker Stop, 283*bb4ee6a4SAndroid Build Coastguard Worker Crash, 284*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] 285*bb4ee6a4SAndroid Build Coastguard Worker GuestPanic, 286*bb4ee6a4SAndroid Build Coastguard Worker WatchdogReset, 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker 289*bb4ee6a4SAndroid Build Coastguard Worker type DeviceResult<T = VirtioDeviceStub> = Result<T>; 290*bb4ee6a4SAndroid Build Coastguard Worker 291*bb4ee6a4SAndroid Build Coastguard Worker fn create_vhost_user_block_device( 292*bb4ee6a4SAndroid Build Coastguard Worker cfg: &Config, 293*bb4ee6a4SAndroid Build Coastguard Worker connection: Connection<FrontendReq>, 294*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult { 295*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::VhostUserFrontend::new( 296*bb4ee6a4SAndroid Build Coastguard Worker virtio::DeviceType::Block, 297*bb4ee6a4SAndroid Build Coastguard Worker virtio::base_features(cfg.protection_type), 298*bb4ee6a4SAndroid Build Coastguard Worker connection, 299*bb4ee6a4SAndroid Build Coastguard Worker None, 300*bb4ee6a4SAndroid Build Coastguard Worker None, 301*bb4ee6a4SAndroid Build Coastguard Worker ) 302*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 303*bb4ee6a4SAndroid Build Coastguard Worker Exit::VhostUserBlockDeviceNew, 304*bb4ee6a4SAndroid Build Coastguard Worker "failed to set up vhost-user block device", 305*bb4ee6a4SAndroid Build Coastguard Worker )?; 306*bb4ee6a4SAndroid Build Coastguard Worker 307*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 308*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 309*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 310*bb4ee6a4SAndroid Build Coastguard Worker }) 311*bb4ee6a4SAndroid Build Coastguard Worker } 312*bb4ee6a4SAndroid Build Coastguard Worker 313*bb4ee6a4SAndroid Build Coastguard Worker fn create_block_device(cfg: &Config, disk: &DiskOption, disk_device_tube: Tube) -> DeviceResult { 314*bb4ee6a4SAndroid Build Coastguard Worker let features = virtio::base_features(cfg.protection_type); 315*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::BlockAsync::new( 316*bb4ee6a4SAndroid Build Coastguard Worker features, 317*bb4ee6a4SAndroid Build Coastguard Worker disk.open()?, 318*bb4ee6a4SAndroid Build Coastguard Worker disk, 319*bb4ee6a4SAndroid Build Coastguard Worker Some(disk_device_tube), 320*bb4ee6a4SAndroid Build Coastguard Worker None, 321*bb4ee6a4SAndroid Build Coastguard Worker None, 322*bb4ee6a4SAndroid Build Coastguard Worker ) 323*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::BlockDeviceNew, "failed to create block device")?; 324*bb4ee6a4SAndroid Build Coastguard Worker 325*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 326*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 327*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 328*bb4ee6a4SAndroid Build Coastguard Worker }) 329*bb4ee6a4SAndroid Build Coastguard Worker } 330*bb4ee6a4SAndroid Build Coastguard Worker 331*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 332*bb4ee6a4SAndroid Build Coastguard Worker fn create_vhost_user_gpu_device( 333*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64, 334*bb4ee6a4SAndroid Build Coastguard Worker connection: Connection<FrontendReq>, 335*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult { 336*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::VhostUserFrontend::new( 337*bb4ee6a4SAndroid Build Coastguard Worker virtio::DeviceType::Gpu, 338*bb4ee6a4SAndroid Build Coastguard Worker base_features, 339*bb4ee6a4SAndroid Build Coastguard Worker connection, 340*bb4ee6a4SAndroid Build Coastguard Worker None, 341*bb4ee6a4SAndroid Build Coastguard Worker None, 342*bb4ee6a4SAndroid Build Coastguard Worker ) 343*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 344*bb4ee6a4SAndroid Build Coastguard Worker Exit::VhostUserGpuDeviceNew, 345*bb4ee6a4SAndroid Build Coastguard Worker "failed to set up vhost-user gpu device", 346*bb4ee6a4SAndroid Build Coastguard Worker )?; 347*bb4ee6a4SAndroid Build Coastguard Worker 348*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 349*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 350*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 351*bb4ee6a4SAndroid Build Coastguard Worker }) 352*bb4ee6a4SAndroid Build Coastguard Worker } 353*bb4ee6a4SAndroid Build Coastguard Worker 354*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 355*bb4ee6a4SAndroid Build Coastguard Worker fn create_vhost_user_snd_device( 356*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64, 357*bb4ee6a4SAndroid Build Coastguard Worker connection: Connection<FrontendReq>, 358*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult { 359*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::VhostUserFrontend::new( 360*bb4ee6a4SAndroid Build Coastguard Worker virtio::DeviceType::Sound, 361*bb4ee6a4SAndroid Build Coastguard Worker base_features, 362*bb4ee6a4SAndroid Build Coastguard Worker connection, 363*bb4ee6a4SAndroid Build Coastguard Worker None, 364*bb4ee6a4SAndroid Build Coastguard Worker None, 365*bb4ee6a4SAndroid Build Coastguard Worker ) 366*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 367*bb4ee6a4SAndroid Build Coastguard Worker Exit::VhostUserSndDeviceNew, 368*bb4ee6a4SAndroid Build Coastguard Worker "failed to set up vhost-user snd device", 369*bb4ee6a4SAndroid Build Coastguard Worker )?; 370*bb4ee6a4SAndroid Build Coastguard Worker 371*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 372*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 373*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 374*bb4ee6a4SAndroid Build Coastguard Worker }) 375*bb4ee6a4SAndroid Build Coastguard Worker } 376*bb4ee6a4SAndroid Build Coastguard Worker 377*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 378*bb4ee6a4SAndroid Build Coastguard Worker fn create_multi_touch_device( 379*bb4ee6a4SAndroid Build Coastguard Worker cfg: &Config, 380*bb4ee6a4SAndroid Build Coastguard Worker event_pipe: StreamChannel, 381*bb4ee6a4SAndroid Build Coastguard Worker width: u32, 382*bb4ee6a4SAndroid Build Coastguard Worker height: u32, 383*bb4ee6a4SAndroid Build Coastguard Worker name: Option<&str>, 384*bb4ee6a4SAndroid Build Coastguard Worker idx: u32, 385*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult { 386*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::input::new_multi_touch( 387*bb4ee6a4SAndroid Build Coastguard Worker idx, 388*bb4ee6a4SAndroid Build Coastguard Worker event_pipe, 389*bb4ee6a4SAndroid Build Coastguard Worker width, 390*bb4ee6a4SAndroid Build Coastguard Worker height, 391*bb4ee6a4SAndroid Build Coastguard Worker name, 392*bb4ee6a4SAndroid Build Coastguard Worker virtio::base_features(cfg.protection_type), 393*bb4ee6a4SAndroid Build Coastguard Worker ) 394*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::InputDeviceNew, "failed to set up input device")?; 395*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 396*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 397*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 398*bb4ee6a4SAndroid Build Coastguard Worker }) 399*bb4ee6a4SAndroid Build Coastguard Worker } 400*bb4ee6a4SAndroid Build Coastguard Worker 401*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 402*bb4ee6a4SAndroid Build Coastguard Worker fn create_mouse_device(cfg: &Config, event_pipe: StreamChannel, idx: u32) -> DeviceResult { 403*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::input::new_mouse(idx, event_pipe, virtio::base_features(cfg.protection_type)) 404*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::InputDeviceNew, "failed to set up input device")?; 405*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 406*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 407*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 408*bb4ee6a4SAndroid Build Coastguard Worker }) 409*bb4ee6a4SAndroid Build Coastguard Worker } 410*bb4ee6a4SAndroid Build Coastguard Worker 411*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "slirp")] 412*bb4ee6a4SAndroid Build Coastguard Worker fn create_vhost_user_net_device(cfg: &Config, connection: Connection<FrontendReq>) -> DeviceResult { 413*bb4ee6a4SAndroid Build Coastguard Worker let features = virtio::base_features(cfg.protection_type); 414*bb4ee6a4SAndroid Build Coastguard Worker let dev = 415*bb4ee6a4SAndroid Build Coastguard Worker virtio::VhostUserFrontend::new(virtio::DeviceType::Net, features, connection, None, None) 416*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 417*bb4ee6a4SAndroid Build Coastguard Worker Exit::VhostUserNetDeviceNew, 418*bb4ee6a4SAndroid Build Coastguard Worker "failed to set up vhost-user net device", 419*bb4ee6a4SAndroid Build Coastguard Worker )?; 420*bb4ee6a4SAndroid Build Coastguard Worker 421*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 422*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 423*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 424*bb4ee6a4SAndroid Build Coastguard Worker }) 425*bb4ee6a4SAndroid Build Coastguard Worker } 426*bb4ee6a4SAndroid Build Coastguard Worker 427*bb4ee6a4SAndroid Build Coastguard Worker fn create_rng_device(cfg: &Config) -> DeviceResult { 428*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::Rng::new(virtio::base_features(cfg.protection_type)) 429*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::RngDeviceNew, "failed to set up rng")?; 430*bb4ee6a4SAndroid Build Coastguard Worker 431*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 432*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 433*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 434*bb4ee6a4SAndroid Build Coastguard Worker }) 435*bb4ee6a4SAndroid Build Coastguard Worker } 436*bb4ee6a4SAndroid Build Coastguard Worker 437*bb4ee6a4SAndroid Build Coastguard Worker fn create_console_device(cfg: &Config, param: &SerialParameters) -> DeviceResult { 438*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = Vec::new(); 439*bb4ee6a4SAndroid Build Coastguard Worker let evt = Event::new().exit_context(Exit::CreateEvent, "failed to create event")?; 440*bb4ee6a4SAndroid Build Coastguard Worker let dev = param 441*bb4ee6a4SAndroid Build Coastguard Worker .create_serial_device::<Console>(cfg.protection_type, &evt, &mut keep_rds) 442*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CreateConsole, "failed to create console device")?; 443*bb4ee6a4SAndroid Build Coastguard Worker 444*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 445*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 446*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 447*bb4ee6a4SAndroid Build Coastguard Worker }) 448*bb4ee6a4SAndroid Build Coastguard Worker } 449*bb4ee6a4SAndroid Build Coastguard Worker 450*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 451*bb4ee6a4SAndroid Build Coastguard Worker fn create_balloon_device( 452*bb4ee6a4SAndroid Build Coastguard Worker cfg: &Config, 453*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube: Tube, 454*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube: Tube, 455*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube: Option<Tube>, 456*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size: u64, 457*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult { 458*bb4ee6a4SAndroid Build Coastguard Worker let balloon_features = 459*bb4ee6a4SAndroid Build Coastguard Worker (cfg.balloon_page_reporting as u64) << BalloonFeatures::PageReporting as u64; 460*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::Balloon::new( 461*bb4ee6a4SAndroid Build Coastguard Worker virtio::base_features(cfg.protection_type), 462*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube, 463*bb4ee6a4SAndroid Build Coastguard Worker VmMemoryClient::new(dynamic_mapping_device_tube), 464*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube, 465*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size, 466*bb4ee6a4SAndroid Build Coastguard Worker balloon_features, 467*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "registered_events")] 468*bb4ee6a4SAndroid Build Coastguard Worker None, 469*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_BALLOON_WS_DEFAULT_NUM_BINS, 470*bb4ee6a4SAndroid Build Coastguard Worker ) 471*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::BalloonDeviceNew, "failed to create balloon")?; 472*bb4ee6a4SAndroid Build Coastguard Worker 473*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 474*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 475*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 476*bb4ee6a4SAndroid Build Coastguard Worker }) 477*bb4ee6a4SAndroid Build Coastguard Worker } 478*bb4ee6a4SAndroid Build Coastguard Worker 479*bb4ee6a4SAndroid Build Coastguard Worker fn create_vsock_device(cfg: &Config) -> DeviceResult { 480*bb4ee6a4SAndroid Build Coastguard Worker // We only support a single guest, so we can confidently assign a default 481*bb4ee6a4SAndroid Build Coastguard Worker // CID if one isn't provided. We choose the lowest non-reserved value. 482*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::vsock::Vsock::new( 483*bb4ee6a4SAndroid Build Coastguard Worker cfg.vsock 484*bb4ee6a4SAndroid Build Coastguard Worker .as_ref() 485*bb4ee6a4SAndroid Build Coastguard Worker .map(|cfg| cfg.cid) 486*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(DEFAULT_GUEST_CID), 487*bb4ee6a4SAndroid Build Coastguard Worker cfg.host_guid.clone(), 488*bb4ee6a4SAndroid Build Coastguard Worker virtio::base_features(cfg.protection_type), 489*bb4ee6a4SAndroid Build Coastguard Worker ) 490*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 491*bb4ee6a4SAndroid Build Coastguard Worker Exit::UserspaceVsockDeviceNew, 492*bb4ee6a4SAndroid Build Coastguard Worker "failed to create userspace vsock device", 493*bb4ee6a4SAndroid Build Coastguard Worker )?; 494*bb4ee6a4SAndroid Build Coastguard Worker 495*bb4ee6a4SAndroid Build Coastguard Worker Ok(VirtioDeviceStub { 496*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 497*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 498*bb4ee6a4SAndroid Build Coastguard Worker }) 499*bb4ee6a4SAndroid Build Coastguard Worker } 500*bb4ee6a4SAndroid Build Coastguard Worker 501*bb4ee6a4SAndroid Build Coastguard Worker fn create_virtio_devices( 502*bb4ee6a4SAndroid Build Coastguard Worker cfg: &mut Config, 503*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: &SendTube, 504*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::ptr_arg)] control_tubes: &mut Vec<TaggedControlTube>, 505*bb4ee6a4SAndroid Build Coastguard Worker disk_device_tubes: &mut Vec<Tube>, 506*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states: &mut Vec<InitialAudioSessionState>, 507*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube: Option<Tube>, 508*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_device_tube: Option<Tube>, 509*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube: Option<Tube>, 510*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube: Option<Tube>, 511*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size: u64, 512*bb4ee6a4SAndroid Build Coastguard Worker tsc_frequency: u64, 513*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_state_device_tube: Option<Tube>, 514*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_control_device_tube: Option<Tube>, 515*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult<Vec<VirtioDeviceStub>> { 516*bb4ee6a4SAndroid Build Coastguard Worker let mut devs = Vec::new(); 517*bb4ee6a4SAndroid Build Coastguard Worker 518*bb4ee6a4SAndroid Build Coastguard Worker if cfg.block_vhost_user_tube.is_empty() { 519*bb4ee6a4SAndroid Build Coastguard Worker // Disk devices must precede virtio-console devices or the kernel does not boot. 520*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/171215421): figure out why this ordering is required and fix it. 521*bb4ee6a4SAndroid Build Coastguard Worker for disk in &cfg.disks { 522*bb4ee6a4SAndroid Build Coastguard Worker let disk_device_tube = disk_device_tubes.remove(0); 523*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_block_device(cfg, disk, disk_device_tube)?); 524*bb4ee6a4SAndroid Build Coastguard Worker } 525*bb4ee6a4SAndroid Build Coastguard Worker } else { 526*bb4ee6a4SAndroid Build Coastguard Worker info!("Starting up vhost user block backends..."); 527*bb4ee6a4SAndroid Build Coastguard Worker for _disk in &cfg.disks { 528*bb4ee6a4SAndroid Build Coastguard Worker let disk_device_tube = cfg.block_vhost_user_tube.remove(0); 529*bb4ee6a4SAndroid Build Coastguard Worker let connection = Connection::<FrontendReq>::from(disk_device_tube); 530*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_vhost_user_block_device(cfg, connection)?); 531*bb4ee6a4SAndroid Build Coastguard Worker } 532*bb4ee6a4SAndroid Build Coastguard Worker } 533*bb4ee6a4SAndroid Build Coastguard Worker 534*bb4ee6a4SAndroid Build Coastguard Worker for (_, param) in cfg 535*bb4ee6a4SAndroid Build Coastguard Worker .serial_parameters 536*bb4ee6a4SAndroid Build Coastguard Worker .iter() 537*bb4ee6a4SAndroid Build Coastguard Worker .filter(|(_k, v)| v.hardware == SerialHardware::VirtioConsole) 538*bb4ee6a4SAndroid Build Coastguard Worker { 539*bb4ee6a4SAndroid Build Coastguard Worker let dev = create_console_device(cfg, param)?; 540*bb4ee6a4SAndroid Build Coastguard Worker devs.push(dev); 541*bb4ee6a4SAndroid Build Coastguard Worker } 542*bb4ee6a4SAndroid Build Coastguard Worker 543*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 544*bb4ee6a4SAndroid Build Coastguard Worker { 545*bb4ee6a4SAndroid Build Coastguard Worker let snd_split_configs = std::mem::take(&mut cfg.snd_split_configs); 546*bb4ee6a4SAndroid Build Coastguard Worker for mut snd_split_cfg in snd_split_configs.into_iter() { 547*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_virtio_snd_device( 548*bb4ee6a4SAndroid Build Coastguard Worker cfg, 549*bb4ee6a4SAndroid Build Coastguard Worker &mut snd_split_cfg, 550*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 551*bb4ee6a4SAndroid Build Coastguard Worker )?); 552*bb4ee6a4SAndroid Build Coastguard Worker if let Some(vmm_config) = snd_split_cfg.vmm_config { 553*bb4ee6a4SAndroid Build Coastguard Worker let initial_audio_session_state = InitialAudioSessionState { 554*bb4ee6a4SAndroid Build Coastguard Worker audio_client_guid: vmm_config.audio_client_guid, 555*bb4ee6a4SAndroid Build Coastguard Worker card_index: vmm_config.card_index, 556*bb4ee6a4SAndroid Build Coastguard Worker }; 557*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states.push(initial_audio_session_state); 558*bb4ee6a4SAndroid Build Coastguard Worker } 559*bb4ee6a4SAndroid Build Coastguard Worker } 560*bb4ee6a4SAndroid Build Coastguard Worker } 561*bb4ee6a4SAndroid Build Coastguard Worker 562*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 563*bb4ee6a4SAndroid Build Coastguard Worker if let Some(tube) = pvclock_device_tube { 564*bb4ee6a4SAndroid Build Coastguard Worker product::push_pvclock_device(cfg, &mut devs, tsc_frequency, tube); 565*bb4ee6a4SAndroid Build Coastguard Worker } 566*bb4ee6a4SAndroid Build Coastguard Worker 567*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_rng_device(cfg)?); 568*bb4ee6a4SAndroid Build Coastguard Worker 569*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "slirp")] 570*bb4ee6a4SAndroid Build Coastguard Worker if let Some(net_vhost_user_tube) = cfg.net_vhost_user_tube.take() { 571*bb4ee6a4SAndroid Build Coastguard Worker let connection = Connection::<FrontendReq>::from(net_vhost_user_tube); 572*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_vhost_user_net_device(cfg, connection)?); 573*bb4ee6a4SAndroid Build Coastguard Worker } 574*bb4ee6a4SAndroid Build Coastguard Worker 575*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 576*bb4ee6a4SAndroid Build Coastguard Worker if let (Some(balloon_device_tube), Some(dynamic_mapping_device_tube)) = 577*bb4ee6a4SAndroid Build Coastguard Worker (balloon_device_tube, dynamic_mapping_device_tube) 578*bb4ee6a4SAndroid Build Coastguard Worker { 579*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_balloon_device( 580*bb4ee6a4SAndroid Build Coastguard Worker cfg, 581*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube, 582*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube, 583*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube, 584*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size, 585*bb4ee6a4SAndroid Build Coastguard Worker )?); 586*bb4ee6a4SAndroid Build Coastguard Worker } 587*bb4ee6a4SAndroid Build Coastguard Worker 588*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_vsock_device(cfg)?); 589*bb4ee6a4SAndroid Build Coastguard Worker 590*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 591*bb4ee6a4SAndroid Build Coastguard Worker let event_devices = if let Some(InputEventSplitConfig { 592*bb4ee6a4SAndroid Build Coastguard Worker backend_config, 593*bb4ee6a4SAndroid Build Coastguard Worker vmm_config, 594*bb4ee6a4SAndroid Build Coastguard Worker }) = cfg.input_event_split_config.take() 595*bb4ee6a4SAndroid Build Coastguard Worker { 596*bb4ee6a4SAndroid Build Coastguard Worker devs.extend( 597*bb4ee6a4SAndroid Build Coastguard Worker create_virtio_input_event_devices(cfg, vmm_config) 598*bb4ee6a4SAndroid Build Coastguard Worker .context("create input event devices")?, 599*bb4ee6a4SAndroid Build Coastguard Worker ); 600*bb4ee6a4SAndroid Build Coastguard Worker backend_config.map(|cfg| cfg.event_devices) 601*bb4ee6a4SAndroid Build Coastguard Worker } else { 602*bb4ee6a4SAndroid Build Coastguard Worker None 603*bb4ee6a4SAndroid Build Coastguard Worker }; 604*bb4ee6a4SAndroid Build Coastguard Worker 605*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 606*bb4ee6a4SAndroid Build Coastguard Worker if let Some(wndproc_thread_vmm_config) = cfg 607*bb4ee6a4SAndroid Build Coastguard Worker .window_procedure_thread_split_config 608*bb4ee6a4SAndroid Build Coastguard Worker .as_mut() 609*bb4ee6a4SAndroid Build Coastguard Worker .map(|split_cfg| &mut split_cfg.vmm_config) 610*bb4ee6a4SAndroid Build Coastguard Worker { 611*bb4ee6a4SAndroid Build Coastguard Worker product::push_window_procedure_thread_control_tubes( 612*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 613*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread_vmm_config, 614*bb4ee6a4SAndroid Build Coastguard Worker ); 615*bb4ee6a4SAndroid Build Coastguard Worker } 616*bb4ee6a4SAndroid Build Coastguard Worker 617*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 618*bb4ee6a4SAndroid Build Coastguard Worker let mut wndproc_thread = cfg 619*bb4ee6a4SAndroid Build Coastguard Worker .window_procedure_thread_split_config 620*bb4ee6a4SAndroid Build Coastguard Worker .as_mut() 621*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|cfg| cfg.wndproc_thread_builder.take()) 622*bb4ee6a4SAndroid Build Coastguard Worker .map(WindowProcedureThreadBuilder::start_thread) 623*bb4ee6a4SAndroid Build Coastguard Worker .transpose() 624*bb4ee6a4SAndroid Build Coastguard Worker .context("Failed to start the window procedure thread.")?; 625*bb4ee6a4SAndroid Build Coastguard Worker 626*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 627*bb4ee6a4SAndroid Build Coastguard Worker if let Some(gpu_vmm_config) = cfg.gpu_vmm_config.take() { 628*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_virtio_gpu_device( 629*bb4ee6a4SAndroid Build Coastguard Worker cfg, 630*bb4ee6a4SAndroid Build Coastguard Worker gpu_vmm_config, 631*bb4ee6a4SAndroid Build Coastguard Worker event_devices, 632*bb4ee6a4SAndroid Build Coastguard Worker &mut wndproc_thread, 633*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 634*bb4ee6a4SAndroid Build Coastguard Worker )?); 635*bb4ee6a4SAndroid Build Coastguard Worker } 636*bb4ee6a4SAndroid Build Coastguard Worker 637*bb4ee6a4SAndroid Build Coastguard Worker Ok(devs) 638*bb4ee6a4SAndroid Build Coastguard Worker } 639*bb4ee6a4SAndroid Build Coastguard Worker 640*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 641*bb4ee6a4SAndroid Build Coastguard Worker fn create_virtio_input_event_devices( 642*bb4ee6a4SAndroid Build Coastguard Worker cfg: &Config, 643*bb4ee6a4SAndroid Build Coastguard Worker mut input_event_vmm_config: InputEventVmmConfig, 644*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult<Vec<VirtioDeviceStub>> { 645*bb4ee6a4SAndroid Build Coastguard Worker let mut devs = Vec::new(); 646*bb4ee6a4SAndroid Build Coastguard Worker 647*bb4ee6a4SAndroid Build Coastguard Worker // Iterate event devices, create the VMM end. 648*bb4ee6a4SAndroid Build Coastguard Worker let mut multi_touch_pipes = input_event_vmm_config 649*bb4ee6a4SAndroid Build Coastguard Worker .multi_touch_pipes 650*bb4ee6a4SAndroid Build Coastguard Worker .drain(..) 651*bb4ee6a4SAndroid Build Coastguard Worker .enumerate(); 652*bb4ee6a4SAndroid Build Coastguard Worker for input in &cfg.virtio_input { 653*bb4ee6a4SAndroid Build Coastguard Worker match input { 654*bb4ee6a4SAndroid Build Coastguard Worker InputDeviceOption::SingleTouch { .. } => { 655*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("--single-touch is no longer supported. Use --multi-touch instead."); 656*bb4ee6a4SAndroid Build Coastguard Worker } 657*bb4ee6a4SAndroid Build Coastguard Worker InputDeviceOption::MultiTouch { 658*bb4ee6a4SAndroid Build Coastguard Worker width, 659*bb4ee6a4SAndroid Build Coastguard Worker height, 660*bb4ee6a4SAndroid Build Coastguard Worker name, 661*bb4ee6a4SAndroid Build Coastguard Worker .. 662*bb4ee6a4SAndroid Build Coastguard Worker } => { 663*bb4ee6a4SAndroid Build Coastguard Worker let Some((idx, pipe)) = multi_touch_pipes.next() else { 664*bb4ee6a4SAndroid Build Coastguard Worker break; 665*bb4ee6a4SAndroid Build Coastguard Worker }; 666*bb4ee6a4SAndroid Build Coastguard Worker let mut width = *width; 667*bb4ee6a4SAndroid Build Coastguard Worker let mut height = *height; 668*bb4ee6a4SAndroid Build Coastguard Worker if idx == 0 { 669*bb4ee6a4SAndroid Build Coastguard Worker if width.is_none() { 670*bb4ee6a4SAndroid Build Coastguard Worker width = cfg.display_input_width; 671*bb4ee6a4SAndroid Build Coastguard Worker } 672*bb4ee6a4SAndroid Build Coastguard Worker if height.is_none() { 673*bb4ee6a4SAndroid Build Coastguard Worker height = cfg.display_input_height; 674*bb4ee6a4SAndroid Build Coastguard Worker } 675*bb4ee6a4SAndroid Build Coastguard Worker } 676*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_multi_touch_device( 677*bb4ee6a4SAndroid Build Coastguard Worker cfg, 678*bb4ee6a4SAndroid Build Coastguard Worker pipe, 679*bb4ee6a4SAndroid Build Coastguard Worker width.unwrap_or(DEFAULT_TOUCH_DEVICE_WIDTH), 680*bb4ee6a4SAndroid Build Coastguard Worker height.unwrap_or(DEFAULT_TOUCH_DEVICE_HEIGHT), 681*bb4ee6a4SAndroid Build Coastguard Worker name.as_deref(), 682*bb4ee6a4SAndroid Build Coastguard Worker idx as u32, 683*bb4ee6a4SAndroid Build Coastguard Worker )?); 684*bb4ee6a4SAndroid Build Coastguard Worker } 685*bb4ee6a4SAndroid Build Coastguard Worker _ => {} 686*bb4ee6a4SAndroid Build Coastguard Worker } 687*bb4ee6a4SAndroid Build Coastguard Worker } 688*bb4ee6a4SAndroid Build Coastguard Worker drop(multi_touch_pipes); 689*bb4ee6a4SAndroid Build Coastguard Worker 690*bb4ee6a4SAndroid Build Coastguard Worker product::push_mouse_device(cfg, &mut input_event_vmm_config, &mut devs)?; 691*bb4ee6a4SAndroid Build Coastguard Worker 692*bb4ee6a4SAndroid Build Coastguard Worker for (idx, pipe) in input_event_vmm_config.mouse_pipes.drain(..).enumerate() { 693*bb4ee6a4SAndroid Build Coastguard Worker devs.push(create_mouse_device(cfg, pipe, idx as u32)?); 694*bb4ee6a4SAndroid Build Coastguard Worker } 695*bb4ee6a4SAndroid Build Coastguard Worker 696*bb4ee6a4SAndroid Build Coastguard Worker let keyboard_pipe = input_event_vmm_config 697*bb4ee6a4SAndroid Build Coastguard Worker .keyboard_pipes 698*bb4ee6a4SAndroid Build Coastguard Worker .pop() 699*bb4ee6a4SAndroid Build Coastguard Worker .expect("at least one keyboard should be in GPU VMM config"); 700*bb4ee6a4SAndroid Build Coastguard Worker let dev = virtio::input::new_keyboard( 701*bb4ee6a4SAndroid Build Coastguard Worker /* idx= */ 0, 702*bb4ee6a4SAndroid Build Coastguard Worker keyboard_pipe, 703*bb4ee6a4SAndroid Build Coastguard Worker virtio::base_features(cfg.protection_type), 704*bb4ee6a4SAndroid Build Coastguard Worker ) 705*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::InputDeviceNew, "failed to set up input device")?; 706*bb4ee6a4SAndroid Build Coastguard Worker 707*bb4ee6a4SAndroid Build Coastguard Worker devs.push(VirtioDeviceStub { 708*bb4ee6a4SAndroid Build Coastguard Worker dev: Box::new(dev), 709*bb4ee6a4SAndroid Build Coastguard Worker jail: None, 710*bb4ee6a4SAndroid Build Coastguard Worker }); 711*bb4ee6a4SAndroid Build Coastguard Worker 712*bb4ee6a4SAndroid Build Coastguard Worker Ok(devs) 713*bb4ee6a4SAndroid Build Coastguard Worker } 714*bb4ee6a4SAndroid Build Coastguard Worker 715*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 716*bb4ee6a4SAndroid Build Coastguard Worker fn create_virtio_gpu_device( 717*bb4ee6a4SAndroid Build Coastguard Worker cfg: &mut Config, 718*bb4ee6a4SAndroid Build Coastguard Worker mut gpu_vmm_config: GpuVmmConfig, 719*bb4ee6a4SAndroid Build Coastguard Worker event_devices: Option<Vec<EventDevice>>, 720*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread: &mut Option<WindowProcedureThread>, 721*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::ptr_arg)] control_tubes: &mut Vec<TaggedControlTube>, 722*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult<VirtioDeviceStub> { 723*bb4ee6a4SAndroid Build Coastguard Worker let resource_bridges = Vec::<Tube>::new(); 724*bb4ee6a4SAndroid Build Coastguard Worker 725*bb4ee6a4SAndroid Build Coastguard Worker product::push_gpu_control_tubes(control_tubes, &mut gpu_vmm_config); 726*bb4ee6a4SAndroid Build Coastguard Worker 727*bb4ee6a4SAndroid Build Coastguard Worker // If the GPU backend is passed, start up the vhost-user worker in the main process. 728*bb4ee6a4SAndroid Build Coastguard Worker if let Some(backend_config) = cfg.gpu_backend_config.take() { 729*bb4ee6a4SAndroid Build Coastguard Worker let event_devices = event_devices.ok_or_else(|| { 730*bb4ee6a4SAndroid Build Coastguard Worker anyhow!("event devices are missing when creating virtio-gpu in the current process.") 731*bb4ee6a4SAndroid Build Coastguard Worker })?; 732*bb4ee6a4SAndroid Build Coastguard Worker let wndproc_thread = wndproc_thread 733*bb4ee6a4SAndroid Build Coastguard Worker .take() 734*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| anyhow!("Window procedure thread is missing."))?; 735*bb4ee6a4SAndroid Build Coastguard Worker 736*bb4ee6a4SAndroid Build Coastguard Worker std::thread::spawn(move || { 737*bb4ee6a4SAndroid Build Coastguard Worker run_gpu_device_worker(backend_config, event_devices, wndproc_thread) 738*bb4ee6a4SAndroid Build Coastguard Worker }); 739*bb4ee6a4SAndroid Build Coastguard Worker } 740*bb4ee6a4SAndroid Build Coastguard Worker 741*bb4ee6a4SAndroid Build Coastguard Worker // The GPU is always vhost-user, even if running in the main process. 742*bb4ee6a4SAndroid Build Coastguard Worker let gpu_device_tube = gpu_vmm_config 743*bb4ee6a4SAndroid Build Coastguard Worker .main_vhost_user_tube 744*bb4ee6a4SAndroid Build Coastguard Worker .take() 745*bb4ee6a4SAndroid Build Coastguard Worker .expect("GPU VMM vhost-user tube should be set"); 746*bb4ee6a4SAndroid Build Coastguard Worker let connection = Connection::<FrontendReq>::from(gpu_device_tube); 747*bb4ee6a4SAndroid Build Coastguard Worker 748*bb4ee6a4SAndroid Build Coastguard Worker create_vhost_user_gpu_device(virtio::base_features(cfg.protection_type), connection) 749*bb4ee6a4SAndroid Build Coastguard Worker .context("create vhost-user GPU device") 750*bb4ee6a4SAndroid Build Coastguard Worker } 751*bb4ee6a4SAndroid Build Coastguard Worker 752*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")] 753*bb4ee6a4SAndroid Build Coastguard Worker fn create_virtio_snd_device( 754*bb4ee6a4SAndroid Build Coastguard Worker cfg: &mut Config, 755*bb4ee6a4SAndroid Build Coastguard Worker snd_split_config: &mut SndSplitConfig, 756*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::ptr_arg)] control_tubes: &mut Vec<TaggedControlTube>, 757*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult<VirtioDeviceStub> { 758*bb4ee6a4SAndroid Build Coastguard Worker let snd_vmm_config = snd_split_config 759*bb4ee6a4SAndroid Build Coastguard Worker .vmm_config 760*bb4ee6a4SAndroid Build Coastguard Worker .as_mut() 761*bb4ee6a4SAndroid Build Coastguard Worker .expect("snd_vmm_config must exist"); 762*bb4ee6a4SAndroid Build Coastguard Worker product::push_snd_control_tubes(control_tubes, snd_vmm_config); 763*bb4ee6a4SAndroid Build Coastguard Worker 764*bb4ee6a4SAndroid Build Coastguard Worker // If the SND backend is passed, start up the vhost-user worker in the main process. 765*bb4ee6a4SAndroid Build Coastguard Worker if let Some(backend_config) = snd_split_config.backend_config.take() { 766*bb4ee6a4SAndroid Build Coastguard Worker std::thread::spawn(move || run_snd_device_worker(backend_config)); 767*bb4ee6a4SAndroid Build Coastguard Worker } 768*bb4ee6a4SAndroid Build Coastguard Worker 769*bb4ee6a4SAndroid Build Coastguard Worker // The SND is always vhost-user, even if running in the main process. 770*bb4ee6a4SAndroid Build Coastguard Worker let snd_device_tube = snd_vmm_config 771*bb4ee6a4SAndroid Build Coastguard Worker .main_vhost_user_tube 772*bb4ee6a4SAndroid Build Coastguard Worker .take() 773*bb4ee6a4SAndroid Build Coastguard Worker .expect("Snd VMM vhost-user tube should be set"); 774*bb4ee6a4SAndroid Build Coastguard Worker let connection = Connection::<FrontendReq>::from(snd_device_tube); 775*bb4ee6a4SAndroid Build Coastguard Worker 776*bb4ee6a4SAndroid Build Coastguard Worker create_vhost_user_snd_device(virtio::base_features(cfg.protection_type), connection) 777*bb4ee6a4SAndroid Build Coastguard Worker .context("create vhost-user SND device") 778*bb4ee6a4SAndroid Build Coastguard Worker } 779*bb4ee6a4SAndroid Build Coastguard Worker 780*bb4ee6a4SAndroid Build Coastguard Worker fn create_devices( 781*bb4ee6a4SAndroid Build Coastguard Worker cfg: &mut Config, 782*bb4ee6a4SAndroid Build Coastguard Worker mem: &GuestMemory, 783*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: &SendTube, 784*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes: &mut Vec<Tube>, 785*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes: &mut Vec<Tube>, 786*bb4ee6a4SAndroid Build Coastguard Worker control_tubes: &mut Vec<TaggedControlTube>, 787*bb4ee6a4SAndroid Build Coastguard Worker disk_device_tubes: &mut Vec<Tube>, 788*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states: &mut Vec<InitialAudioSessionState>, 789*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube: Option<Tube>, 790*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_device_tube: Option<Tube>, 791*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube: Option<Tube>, 792*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube: Option<Tube>, 793*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size: u64, 794*bb4ee6a4SAndroid Build Coastguard Worker tsc_frequency: u64, 795*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_state_device_tube: Option<Tube>, 796*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_control_device_tube: Option<Tube>, 797*bb4ee6a4SAndroid Build Coastguard Worker ) -> DeviceResult<Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>> { 798*bb4ee6a4SAndroid Build Coastguard Worker let stubs = create_virtio_devices( 799*bb4ee6a4SAndroid Build Coastguard Worker cfg, 800*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube, 801*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 802*bb4ee6a4SAndroid Build Coastguard Worker disk_device_tubes, 803*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states, 804*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube, 805*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 806*bb4ee6a4SAndroid Build Coastguard Worker pvclock_device_tube, 807*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube, 808*bb4ee6a4SAndroid Build Coastguard Worker inflate_tube, 809*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size, 810*bb4ee6a4SAndroid Build Coastguard Worker tsc_frequency, 811*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_state_device_tube, 812*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_control_device_tube, 813*bb4ee6a4SAndroid Build Coastguard Worker )?; 814*bb4ee6a4SAndroid Build Coastguard Worker 815*bb4ee6a4SAndroid Build Coastguard Worker let mut pci_devices = Vec::new(); 816*bb4ee6a4SAndroid Build Coastguard Worker 817*bb4ee6a4SAndroid Build Coastguard Worker for stub in stubs { 818*bb4ee6a4SAndroid Build Coastguard Worker let (msi_host_tube, msi_device_tube) = 819*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 820*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes.push(msi_host_tube); 821*bb4ee6a4SAndroid Build Coastguard Worker 822*bb4ee6a4SAndroid Build Coastguard Worker let shared_memory_tube = if stub.dev.get_shared_memory_region().is_some() { 823*bb4ee6a4SAndroid Build Coastguard Worker let (host_tube, device_tube) = 824*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().context("failed to create VVU proxy tube")?; 825*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes.push(host_tube); 826*bb4ee6a4SAndroid Build Coastguard Worker Some(device_tube) 827*bb4ee6a4SAndroid Build Coastguard Worker } else { 828*bb4ee6a4SAndroid Build Coastguard Worker None 829*bb4ee6a4SAndroid Build Coastguard Worker }; 830*bb4ee6a4SAndroid Build Coastguard Worker 831*bb4ee6a4SAndroid Build Coastguard Worker let (ioevent_host_tube, ioevent_device_tube) = 832*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().context("failed to create ioevent tube")?; 833*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes.push(ioevent_host_tube); 834*bb4ee6a4SAndroid Build Coastguard Worker 835*bb4ee6a4SAndroid Build Coastguard Worker let (vm_control_host_tube, vm_control_device_tube) = 836*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().context("failed to create vm_control tube")?; 837*bb4ee6a4SAndroid Build Coastguard Worker control_tubes.push(TaggedControlTube::Vm(FlushOnDropTube::from( 838*bb4ee6a4SAndroid Build Coastguard Worker vm_control_host_tube, 839*bb4ee6a4SAndroid Build Coastguard Worker ))); 840*bb4ee6a4SAndroid Build Coastguard Worker 841*bb4ee6a4SAndroid Build Coastguard Worker let dev = Box::new( 842*bb4ee6a4SAndroid Build Coastguard Worker VirtioPciDevice::new( 843*bb4ee6a4SAndroid Build Coastguard Worker mem.clone(), 844*bb4ee6a4SAndroid Build Coastguard Worker stub.dev, 845*bb4ee6a4SAndroid Build Coastguard Worker msi_device_tube, 846*bb4ee6a4SAndroid Build Coastguard Worker cfg.disable_virtio_intx, 847*bb4ee6a4SAndroid Build Coastguard Worker shared_memory_tube.map(VmMemoryClient::new), 848*bb4ee6a4SAndroid Build Coastguard Worker VmMemoryClient::new(ioevent_device_tube), 849*bb4ee6a4SAndroid Build Coastguard Worker vm_control_device_tube, 850*bb4ee6a4SAndroid Build Coastguard Worker ) 851*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::VirtioPciDev, "failed to create virtio pci dev")?, 852*bb4ee6a4SAndroid Build Coastguard Worker ) as Box<dyn BusDeviceObj>; 853*bb4ee6a4SAndroid Build Coastguard Worker pci_devices.push((dev, stub.jail)); 854*bb4ee6a4SAndroid Build Coastguard Worker } 855*bb4ee6a4SAndroid Build Coastguard Worker 856*bb4ee6a4SAndroid Build Coastguard Worker Ok(pci_devices) 857*bb4ee6a4SAndroid Build Coastguard Worker } 858*bb4ee6a4SAndroid Build Coastguard Worker 859*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 860*bb4ee6a4SAndroid Build Coastguard Worker struct PvClockError(String); 861*bb4ee6a4SAndroid Build Coastguard Worker 862*bb4ee6a4SAndroid Build Coastguard Worker fn handle_readable_event<V: VmArch + 'static, Vcpu: VcpuArch + 'static>( 863*bb4ee6a4SAndroid Build Coastguard Worker event: &TriggeredEvent<Token>, 864*bb4ee6a4SAndroid Build Coastguard Worker vm_control_ids_to_remove: &mut Vec<usize>, 865*bb4ee6a4SAndroid Build Coastguard Worker next_control_id: &mut usize, 866*bb4ee6a4SAndroid Build Coastguard Worker service_vm_state: &mut ServiceVmState, 867*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes: &[Tube], 868*bb4ee6a4SAndroid Build Coastguard Worker ipc_main_loop_tube: Option<&Tube>, 869*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] gpu_control_tube: Option<&Tube>, 870*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube: &RecvTube, 871*bb4ee6a4SAndroid Build Coastguard Worker control_tubes: &mut BTreeMap<usize, TaggedControlTube>, 872*bb4ee6a4SAndroid Build Coastguard Worker guest_os: &mut RunnableLinuxVm<V, Vcpu>, 873*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator_mutex: &Arc<Mutex<SystemAllocator>>, 874*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_host_mute_tubes: &mut [Tube], 875*bb4ee6a4SAndroid Build Coastguard Worker proto_main_loop_tube: Option<&ProtoTube>, 876*bb4ee6a4SAndroid Build Coastguard Worker anti_tamper_main_thread_tube: &Option<ProtoTube>, 877*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] mut balloon_tube: Option<&mut BalloonTube>, 878*bb4ee6a4SAndroid Build Coastguard Worker memory_size_mb: u64, 879*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: &Mutex<Vec<Box<dyn VcpuArch>>>, 880*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_host_tube: &Option<Tube>, 881*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc: &VcpuRunMode, 882*bb4ee6a4SAndroid Build Coastguard Worker region_state: &mut VmMemoryRegionState, 883*bb4ee6a4SAndroid Build Coastguard Worker vm_control_server: Option<&mut ControlServer>, 884*bb4ee6a4SAndroid Build Coastguard Worker irq_handler_control: &Tube, 885*bb4ee6a4SAndroid Build Coastguard Worker device_ctrl_tube: &Tube, 886*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &WaitContext<Token>, 887*bb4ee6a4SAndroid Build Coastguard Worker force_s2idle: bool, 888*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_channels: &[mpsc::Sender<VcpuControl>], 889*bb4ee6a4SAndroid Build Coastguard Worker suspended_pvclock_state: &mut Option<hypervisor::ClockState>, 890*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<ExitState>> { 891*bb4ee6a4SAndroid Build Coastguard Worker let mut execute_vm_request = |request: VmRequest, guest_os: &mut RunnableLinuxVm<V, Vcpu>| { 892*bb4ee6a4SAndroid Build Coastguard Worker if let VmRequest::Exit = request { 893*bb4ee6a4SAndroid Build Coastguard Worker return (VmResponse::Ok, Some(VmRunMode::Exiting)); 894*bb4ee6a4SAndroid Build Coastguard Worker } 895*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_size = vcpu_boxes.lock().len(); 896*bb4ee6a4SAndroid Build Coastguard Worker let resp = request.execute( 897*bb4ee6a4SAndroid Build Coastguard Worker &guest_os.vm, 898*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes, 899*bb4ee6a4SAndroid Build Coastguard Worker &mut guest_os.pm, 900*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 901*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube, 902*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(feature = "gpu"))] 903*bb4ee6a4SAndroid Build Coastguard Worker None, 904*bb4ee6a4SAndroid Build Coastguard Worker None, 905*bb4ee6a4SAndroid Build Coastguard Worker &mut None, 906*bb4ee6a4SAndroid Build Coastguard Worker |msg| { 907*bb4ee6a4SAndroid Build Coastguard Worker kick_all_vcpus( 908*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc, 909*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_channels, 910*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes, 911*bb4ee6a4SAndroid Build Coastguard Worker guest_os.irq_chip.as_ref(), 912*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 913*bb4ee6a4SAndroid Build Coastguard Worker pvclock_host_tube, 914*bb4ee6a4SAndroid Build Coastguard Worker &guest_os.resume_notify_devices, 915*bb4ee6a4SAndroid Build Coastguard Worker msg, 916*bb4ee6a4SAndroid Build Coastguard Worker ); 917*bb4ee6a4SAndroid Build Coastguard Worker }, 918*bb4ee6a4SAndroid Build Coastguard Worker force_s2idle, 919*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] 920*bb4ee6a4SAndroid Build Coastguard Worker None, 921*bb4ee6a4SAndroid Build Coastguard Worker device_ctrl_tube, 922*bb4ee6a4SAndroid Build Coastguard Worker vcpu_size, 923*bb4ee6a4SAndroid Build Coastguard Worker irq_handler_control, 924*bb4ee6a4SAndroid Build Coastguard Worker || guest_os.irq_chip.as_ref().snapshot(vcpu_size), 925*bb4ee6a4SAndroid Build Coastguard Worker suspended_pvclock_state, 926*bb4ee6a4SAndroid Build Coastguard Worker ); 927*bb4ee6a4SAndroid Build Coastguard Worker (resp, None) 928*bb4ee6a4SAndroid Build Coastguard Worker }; 929*bb4ee6a4SAndroid Build Coastguard Worker 930*bb4ee6a4SAndroid Build Coastguard Worker match event.token { 931*bb4ee6a4SAndroid Build Coastguard Worker Token::VmEvent => match vm_evt_rdtube.recv::<VmEventType>() { 932*bb4ee6a4SAndroid Build Coastguard Worker Ok(vm_event) => { 933*bb4ee6a4SAndroid Build Coastguard Worker let exit_state = match vm_event { 934*bb4ee6a4SAndroid Build Coastguard Worker VmEventType::Exit => { 935*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu requested shutdown"); 936*bb4ee6a4SAndroid Build Coastguard Worker Some(ExitState::Stop) 937*bb4ee6a4SAndroid Build Coastguard Worker } 938*bb4ee6a4SAndroid Build Coastguard Worker VmEventType::Reset => { 939*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu requested reset"); 940*bb4ee6a4SAndroid Build Coastguard Worker Some(ExitState::Reset) 941*bb4ee6a4SAndroid Build Coastguard Worker } 942*bb4ee6a4SAndroid Build Coastguard Worker VmEventType::Crash => { 943*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu crashed"); 944*bb4ee6a4SAndroid Build Coastguard Worker Some(ExitState::Crash) 945*bb4ee6a4SAndroid Build Coastguard Worker } 946*bb4ee6a4SAndroid Build Coastguard Worker VmEventType::Panic(_) => { 947*bb4ee6a4SAndroid Build Coastguard Worker error!("got pvpanic event. this event is not expected on Windows."); 948*bb4ee6a4SAndroid Build Coastguard Worker None 949*bb4ee6a4SAndroid Build Coastguard Worker } 950*bb4ee6a4SAndroid Build Coastguard Worker VmEventType::WatchdogReset => { 951*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu stall detected"); 952*bb4ee6a4SAndroid Build Coastguard Worker Some(ExitState::WatchdogReset) 953*bb4ee6a4SAndroid Build Coastguard Worker } 954*bb4ee6a4SAndroid Build Coastguard Worker }; 955*bb4ee6a4SAndroid Build Coastguard Worker return Ok(exit_state); 956*bb4ee6a4SAndroid Build Coastguard Worker } 957*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 958*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to recv VmEvent: {}", e); 959*bb4ee6a4SAndroid Build Coastguard Worker } 960*bb4ee6a4SAndroid Build Coastguard Worker }, 961*bb4ee6a4SAndroid Build Coastguard Worker Token::BrokerShutdown => { 962*bb4ee6a4SAndroid Build Coastguard Worker info!("main loop got broker shutdown event"); 963*bb4ee6a4SAndroid Build Coastguard Worker return Ok(Some(ExitState::Stop)); 964*bb4ee6a4SAndroid Build Coastguard Worker } 965*bb4ee6a4SAndroid Build Coastguard Worker Token::VmControlServer => { 966*bb4ee6a4SAndroid Build Coastguard Worker let server = 967*bb4ee6a4SAndroid Build Coastguard Worker vm_control_server.expect("control server must exist if this event triggers"); 968*bb4ee6a4SAndroid Build Coastguard Worker let client = server.accept(); 969*bb4ee6a4SAndroid Build Coastguard Worker let id = *next_control_id; 970*bb4ee6a4SAndroid Build Coastguard Worker *next_control_id += 1; 971*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 972*bb4ee6a4SAndroid Build Coastguard Worker .add(client.0.get_read_notifier(), Token::VmControl { id }) 973*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 974*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 975*bb4ee6a4SAndroid Build Coastguard Worker "failed to add trigger to wait context", 976*bb4ee6a4SAndroid Build Coastguard Worker )?; 977*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 978*bb4ee6a4SAndroid Build Coastguard Worker .add(client.0.get_close_notifier(), Token::VmControl { id }) 979*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 980*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 981*bb4ee6a4SAndroid Build Coastguard Worker "failed to add trigger to wait context", 982*bb4ee6a4SAndroid Build Coastguard Worker )?; 983*bb4ee6a4SAndroid Build Coastguard Worker control_tubes.insert(id, TaggedControlTube::Vm(client)); 984*bb4ee6a4SAndroid Build Coastguard Worker } 985*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::collapsible_match)] 986*bb4ee6a4SAndroid Build Coastguard Worker Token::VmControl { id } => { 987*bb4ee6a4SAndroid Build Coastguard Worker if let Some(tube) = control_tubes.get(&id) { 988*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::single_match)] 989*bb4ee6a4SAndroid Build Coastguard Worker match tube { 990*bb4ee6a4SAndroid Build Coastguard Worker TaggedControlTube::Product(product_tube) => { 991*bb4ee6a4SAndroid Build Coastguard Worker product::handle_tagged_control_tube_event( 992*bb4ee6a4SAndroid Build Coastguard Worker product_tube, 993*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_host_mute_tubes, 994*bb4ee6a4SAndroid Build Coastguard Worker service_vm_state, 995*bb4ee6a4SAndroid Build Coastguard Worker ipc_main_loop_tube, 996*bb4ee6a4SAndroid Build Coastguard Worker ) 997*bb4ee6a4SAndroid Build Coastguard Worker } 998*bb4ee6a4SAndroid Build Coastguard Worker TaggedControlTube::Vm(tube) => match tube.0.recv::<VmRequest>() { 999*bb4ee6a4SAndroid Build Coastguard Worker Ok(request) => { 1000*bb4ee6a4SAndroid Build Coastguard Worker let mut run_mode_opt = None; 1001*bb4ee6a4SAndroid Build Coastguard Worker let response = match request { 1002*bb4ee6a4SAndroid Build Coastguard Worker VmRequest::HotPlugVfioCommand { device, add } => { 1003*bb4ee6a4SAndroid Build Coastguard Worker // Suppress warnings. 1004*bb4ee6a4SAndroid Build Coastguard Worker let _ = (device, add); 1005*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("not implemented on Windows"); 1006*bb4ee6a4SAndroid Build Coastguard Worker } 1007*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "registered_events")] 1008*bb4ee6a4SAndroid Build Coastguard Worker VmRequest::RegisterListener { socket_addr, event } => { 1009*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("not implemented on Windows"); 1010*bb4ee6a4SAndroid Build Coastguard Worker } 1011*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "registered_events")] 1012*bb4ee6a4SAndroid Build Coastguard Worker VmRequest::UnregisterListener { socket_addr, event } => { 1013*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("not implemented on Windows"); 1014*bb4ee6a4SAndroid Build Coastguard Worker } 1015*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "registered_events")] 1016*bb4ee6a4SAndroid Build Coastguard Worker VmRequest::Unregister { socket_addr } => { 1017*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("not implemented on Windows"); 1018*bb4ee6a4SAndroid Build Coastguard Worker } 1019*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 1020*bb4ee6a4SAndroid Build Coastguard Worker VmRequest::BalloonCommand(cmd) => { 1021*bb4ee6a4SAndroid Build Coastguard Worker if let Some(balloon_tube) = balloon_tube { 1022*bb4ee6a4SAndroid Build Coastguard Worker if let Some((r, key)) = balloon_tube.send_cmd(cmd, Some(id)) 1023*bb4ee6a4SAndroid Build Coastguard Worker { 1024*bb4ee6a4SAndroid Build Coastguard Worker if key != id { 1025*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("not implemented on Windows"); 1026*bb4ee6a4SAndroid Build Coastguard Worker } 1027*bb4ee6a4SAndroid Build Coastguard Worker Some(r) 1028*bb4ee6a4SAndroid Build Coastguard Worker } else { 1029*bb4ee6a4SAndroid Build Coastguard Worker None 1030*bb4ee6a4SAndroid Build Coastguard Worker } 1031*bb4ee6a4SAndroid Build Coastguard Worker } else { 1032*bb4ee6a4SAndroid Build Coastguard Worker error!("balloon not enabled"); 1033*bb4ee6a4SAndroid Build Coastguard Worker None 1034*bb4ee6a4SAndroid Build Coastguard Worker } 1035*bb4ee6a4SAndroid Build Coastguard Worker } 1036*bb4ee6a4SAndroid Build Coastguard Worker _ => { 1037*bb4ee6a4SAndroid Build Coastguard Worker let (resp, run_mode_ret) = 1038*bb4ee6a4SAndroid Build Coastguard Worker execute_vm_request(request, guest_os); 1039*bb4ee6a4SAndroid Build Coastguard Worker run_mode_opt = run_mode_ret; 1040*bb4ee6a4SAndroid Build Coastguard Worker Some(resp) 1041*bb4ee6a4SAndroid Build Coastguard Worker } 1042*bb4ee6a4SAndroid Build Coastguard Worker }; 1043*bb4ee6a4SAndroid Build Coastguard Worker 1044*bb4ee6a4SAndroid Build Coastguard Worker if let Some(response) = response { 1045*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = tube.0.send(&response) { 1046*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send VmResponse: {}", e); 1047*bb4ee6a4SAndroid Build Coastguard Worker } 1048*bb4ee6a4SAndroid Build Coastguard Worker } 1049*bb4ee6a4SAndroid Build Coastguard Worker if let Some(exit_state) = 1050*bb4ee6a4SAndroid Build Coastguard Worker handle_run_mode_change_for_vm_request(&run_mode_opt, guest_os) 1051*bb4ee6a4SAndroid Build Coastguard Worker { 1052*bb4ee6a4SAndroid Build Coastguard Worker return Ok(Some(exit_state)); 1053*bb4ee6a4SAndroid Build Coastguard Worker } 1054*bb4ee6a4SAndroid Build Coastguard Worker } 1055*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1056*bb4ee6a4SAndroid Build Coastguard Worker if let TubeError::Disconnected = e { 1057*bb4ee6a4SAndroid Build Coastguard Worker vm_control_ids_to_remove.push(id); 1058*bb4ee6a4SAndroid Build Coastguard Worker } else { 1059*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to recv VmRequest: {}", e); 1060*bb4ee6a4SAndroid Build Coastguard Worker } 1061*bb4ee6a4SAndroid Build Coastguard Worker } 1062*bb4ee6a4SAndroid Build Coastguard Worker }, 1063*bb4ee6a4SAndroid Build Coastguard Worker } 1064*bb4ee6a4SAndroid Build Coastguard Worker } 1065*bb4ee6a4SAndroid Build Coastguard Worker } 1066*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 1067*bb4ee6a4SAndroid Build Coastguard Worker Token::BalloonTube => match balloon_tube.as_mut().expect("missing balloon tube").recv() { 1068*bb4ee6a4SAndroid Build Coastguard Worker Ok(resp) => { 1069*bb4ee6a4SAndroid Build Coastguard Worker for (resp, idx) in resp { 1070*bb4ee6a4SAndroid Build Coastguard Worker if let Some(TaggedControlTube::Vm(tube)) = control_tubes.get(&idx) { 1071*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = tube.0.send(&resp) { 1072*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send VmResponse: {}", e); 1073*bb4ee6a4SAndroid Build Coastguard Worker } 1074*bb4ee6a4SAndroid Build Coastguard Worker } else { 1075*bb4ee6a4SAndroid Build Coastguard Worker error!("Bad tube index {}", idx); 1076*bb4ee6a4SAndroid Build Coastguard Worker } 1077*bb4ee6a4SAndroid Build Coastguard Worker } 1078*bb4ee6a4SAndroid Build Coastguard Worker } 1079*bb4ee6a4SAndroid Build Coastguard Worker Err(err) => { 1080*bb4ee6a4SAndroid Build Coastguard Worker error!("Error processing balloon tube {:?}", err) 1081*bb4ee6a4SAndroid Build Coastguard Worker } 1082*bb4ee6a4SAndroid Build Coastguard Worker }, 1083*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(feature = "balloon"))] 1084*bb4ee6a4SAndroid Build Coastguard Worker Token::BalloonTube => unreachable!("balloon tube not registered"), 1085*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unreachable_patterns)] 1086*bb4ee6a4SAndroid Build Coastguard Worker _ => { 1087*bb4ee6a4SAndroid Build Coastguard Worker let run_mode_opt = product::handle_received_token( 1088*bb4ee6a4SAndroid Build Coastguard Worker &event.token, 1089*bb4ee6a4SAndroid Build Coastguard Worker anti_tamper_main_thread_tube, 1090*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 1091*bb4ee6a4SAndroid Build Coastguard Worker balloon_tube, 1092*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 1093*bb4ee6a4SAndroid Build Coastguard Worker guest_os, 1094*bb4ee6a4SAndroid Build Coastguard Worker ipc_main_loop_tube, 1095*bb4ee6a4SAndroid Build Coastguard Worker memory_size_mb, 1096*bb4ee6a4SAndroid Build Coastguard Worker proto_main_loop_tube, 1097*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1098*bb4ee6a4SAndroid Build Coastguard Worker pvclock_host_tube, 1099*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc, 1100*bb4ee6a4SAndroid Build Coastguard Worker service_vm_state, 1101*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes, 1102*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_host_mute_tubes, 1103*bb4ee6a4SAndroid Build Coastguard Worker execute_vm_request, 1104*bb4ee6a4SAndroid Build Coastguard Worker ); 1105*bb4ee6a4SAndroid Build Coastguard Worker if let Some(exit_state) = handle_run_mode_change_for_vm_request(&run_mode_opt, guest_os) 1106*bb4ee6a4SAndroid Build Coastguard Worker { 1107*bb4ee6a4SAndroid Build Coastguard Worker return Ok(Some(exit_state)); 1108*bb4ee6a4SAndroid Build Coastguard Worker } 1109*bb4ee6a4SAndroid Build Coastguard Worker } 1110*bb4ee6a4SAndroid Build Coastguard Worker }; 1111*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 1112*bb4ee6a4SAndroid Build Coastguard Worker } 1113*bb4ee6a4SAndroid Build Coastguard Worker 1114*bb4ee6a4SAndroid Build Coastguard Worker /// Handles a run mode change (if one occurred) if one is pending as a 1115*bb4ee6a4SAndroid Build Coastguard Worker /// result a VmRequest. The parameter, run_mode_opt, is the run mode change 1116*bb4ee6a4SAndroid Build Coastguard Worker /// proposed by the VmRequest's execution. 1117*bb4ee6a4SAndroid Build Coastguard Worker /// 1118*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the exit state, if it changed due to a run mode change. 1119*bb4ee6a4SAndroid Build Coastguard Worker /// None otherwise. 1120*bb4ee6a4SAndroid Build Coastguard Worker fn handle_run_mode_change_for_vm_request<V: VmArch + 'static, Vcpu: VcpuArch + 'static>( 1121*bb4ee6a4SAndroid Build Coastguard Worker run_mode_opt: &Option<VmRunMode>, 1122*bb4ee6a4SAndroid Build Coastguard Worker guest_os: &mut RunnableLinuxVm<V, Vcpu>, 1123*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<ExitState> { 1124*bb4ee6a4SAndroid Build Coastguard Worker if let Some(run_mode) = run_mode_opt { 1125*bb4ee6a4SAndroid Build Coastguard Worker info!("control socket changed run mode to {}", run_mode); 1126*bb4ee6a4SAndroid Build Coastguard Worker match run_mode { 1127*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Exiting => return Some(ExitState::Stop), 1128*bb4ee6a4SAndroid Build Coastguard Worker _ => unreachable!(), 1129*bb4ee6a4SAndroid Build Coastguard Worker } 1130*bb4ee6a4SAndroid Build Coastguard Worker } 1131*bb4ee6a4SAndroid Build Coastguard Worker // No exit state change. 1132*bb4ee6a4SAndroid Build Coastguard Worker None 1133*bb4ee6a4SAndroid Build Coastguard Worker } 1134*bb4ee6a4SAndroid Build Coastguard Worker 1135*bb4ee6a4SAndroid Build Coastguard Worker /// Commands to control the VM Memory handler thread. 1136*bb4ee6a4SAndroid Build Coastguard Worker #[derive(serde::Serialize, serde::Deserialize)] 1137*bb4ee6a4SAndroid Build Coastguard Worker pub enum VmMemoryHandlerRequest { 1138*bb4ee6a4SAndroid Build Coastguard Worker /// No response is sent for this command. 1139*bb4ee6a4SAndroid Build Coastguard Worker Exit, 1140*bb4ee6a4SAndroid Build Coastguard Worker } 1141*bb4ee6a4SAndroid Build Coastguard Worker 1142*bb4ee6a4SAndroid Build Coastguard Worker fn vm_memory_handler_thread( 1143*bb4ee6a4SAndroid Build Coastguard Worker control_tubes: Vec<Tube>, 1144*bb4ee6a4SAndroid Build Coastguard Worker mut vm: impl Vm, 1145*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator_mutex: Arc<Mutex<SystemAllocator>>, 1146*bb4ee6a4SAndroid Build Coastguard Worker mut gralloc: RutabagaGralloc, 1147*bb4ee6a4SAndroid Build Coastguard Worker handler_control: Tube, 1148*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> { 1149*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)] 1150*bb4ee6a4SAndroid Build Coastguard Worker enum Token { 1151*bb4ee6a4SAndroid Build Coastguard Worker VmControl { id: usize }, 1152*bb4ee6a4SAndroid Build Coastguard Worker HandlerControl, 1153*bb4ee6a4SAndroid Build Coastguard Worker } 1154*bb4ee6a4SAndroid Build Coastguard Worker 1155*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx = 1156*bb4ee6a4SAndroid Build Coastguard Worker WaitContext::build_with(&[(handler_control.get_read_notifier(), Token::HandlerControl)]) 1157*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to build wait context")?; 1158*bb4ee6a4SAndroid Build Coastguard Worker let mut control_tubes = BTreeMap::from_iter(control_tubes.into_iter().enumerate()); 1159*bb4ee6a4SAndroid Build Coastguard Worker for (id, socket) in control_tubes.iter() { 1160*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 1161*bb4ee6a4SAndroid Build Coastguard Worker .add(socket.get_read_notifier(), Token::VmControl { id: *id }) 1162*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to add descriptor to wait context")?; 1163*bb4ee6a4SAndroid Build Coastguard Worker } 1164*bb4ee6a4SAndroid Build Coastguard Worker 1165*bb4ee6a4SAndroid Build Coastguard Worker let mut region_state: VmMemoryRegionState = Default::default(); 1166*bb4ee6a4SAndroid Build Coastguard Worker 1167*bb4ee6a4SAndroid Build Coastguard Worker 'wait: loop { 1168*bb4ee6a4SAndroid Build Coastguard Worker let events = { 1169*bb4ee6a4SAndroid Build Coastguard Worker match wait_ctx.wait() { 1170*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v, 1171*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1172*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to poll: {}", e); 1173*bb4ee6a4SAndroid Build Coastguard Worker break; 1174*bb4ee6a4SAndroid Build Coastguard Worker } 1175*bb4ee6a4SAndroid Build Coastguard Worker } 1176*bb4ee6a4SAndroid Build Coastguard Worker }; 1177*bb4ee6a4SAndroid Build Coastguard Worker 1178*bb4ee6a4SAndroid Build Coastguard Worker let mut vm_control_ids_to_remove = Vec::new(); 1179*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) { 1180*bb4ee6a4SAndroid Build Coastguard Worker match event.token { 1181*bb4ee6a4SAndroid Build Coastguard Worker Token::HandlerControl => match handler_control.recv::<VmMemoryHandlerRequest>() { 1182*bb4ee6a4SAndroid Build Coastguard Worker Ok(request) => match request { 1183*bb4ee6a4SAndroid Build Coastguard Worker VmMemoryHandlerRequest::Exit => break 'wait, 1184*bb4ee6a4SAndroid Build Coastguard Worker }, 1185*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1186*bb4ee6a4SAndroid Build Coastguard Worker if let TubeError::Disconnected = e { 1187*bb4ee6a4SAndroid Build Coastguard Worker panic!("vm memory control tube disconnected."); 1188*bb4ee6a4SAndroid Build Coastguard Worker } else { 1189*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to recv VmMemoryHandlerRequest: {}", e); 1190*bb4ee6a4SAndroid Build Coastguard Worker } 1191*bb4ee6a4SAndroid Build Coastguard Worker } 1192*bb4ee6a4SAndroid Build Coastguard Worker }, 1193*bb4ee6a4SAndroid Build Coastguard Worker 1194*bb4ee6a4SAndroid Build Coastguard Worker Token::VmControl { id } => { 1195*bb4ee6a4SAndroid Build Coastguard Worker if let Some(tube) = control_tubes.get(&id) { 1196*bb4ee6a4SAndroid Build Coastguard Worker match tube.recv::<VmMemoryRequest>() { 1197*bb4ee6a4SAndroid Build Coastguard Worker Ok(request) => { 1198*bb4ee6a4SAndroid Build Coastguard Worker let response = request.execute( 1199*bb4ee6a4SAndroid Build Coastguard Worker &mut vm, 1200*bb4ee6a4SAndroid Build Coastguard Worker &mut sys_allocator_mutex.lock(), 1201*bb4ee6a4SAndroid Build Coastguard Worker &mut gralloc, 1202*bb4ee6a4SAndroid Build Coastguard Worker None, 1203*bb4ee6a4SAndroid Build Coastguard Worker &mut region_state, 1204*bb4ee6a4SAndroid Build Coastguard Worker ); 1205*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = tube.send(&response) { 1206*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send VmMemoryControlResponse: {}", e); 1207*bb4ee6a4SAndroid Build Coastguard Worker } 1208*bb4ee6a4SAndroid Build Coastguard Worker } 1209*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1210*bb4ee6a4SAndroid Build Coastguard Worker if let TubeError::Disconnected = e { 1211*bb4ee6a4SAndroid Build Coastguard Worker vm_control_ids_to_remove.push(id); 1212*bb4ee6a4SAndroid Build Coastguard Worker } else { 1213*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to recv VmMemoryControlRequest: {}", e); 1214*bb4ee6a4SAndroid Build Coastguard Worker } 1215*bb4ee6a4SAndroid Build Coastguard Worker } 1216*bb4ee6a4SAndroid Build Coastguard Worker } 1217*bb4ee6a4SAndroid Build Coastguard Worker } 1218*bb4ee6a4SAndroid Build Coastguard Worker } 1219*bb4ee6a4SAndroid Build Coastguard Worker } 1220*bb4ee6a4SAndroid Build Coastguard Worker } 1221*bb4ee6a4SAndroid Build Coastguard Worker 1222*bb4ee6a4SAndroid Build Coastguard Worker remove_closed_tubes(&wait_ctx, &mut control_tubes, vm_control_ids_to_remove)?; 1223*bb4ee6a4SAndroid Build Coastguard Worker if events 1224*bb4ee6a4SAndroid Build Coastguard Worker .iter() 1225*bb4ee6a4SAndroid Build Coastguard Worker .any(|e| e.is_hungup && !e.is_readable && matches!(e.token, Token::HandlerControl)) 1226*bb4ee6a4SAndroid Build Coastguard Worker { 1227*bb4ee6a4SAndroid Build Coastguard Worker error!("vm memory handler control hung up but did not request an exit."); 1228*bb4ee6a4SAndroid Build Coastguard Worker break 'wait; 1229*bb4ee6a4SAndroid Build Coastguard Worker } 1230*bb4ee6a4SAndroid Build Coastguard Worker } 1231*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 1232*bb4ee6a4SAndroid Build Coastguard Worker } 1233*bb4ee6a4SAndroid Build Coastguard Worker 1234*bb4ee6a4SAndroid Build Coastguard Worker fn create_control_server( 1235*bb4ee6a4SAndroid Build Coastguard Worker control_server_path: Option<PathBuf>, 1236*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &WaitContext<Token>, 1237*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<ControlServer>> { 1238*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(feature = "prod-build"))] 1239*bb4ee6a4SAndroid Build Coastguard Worker { 1240*bb4ee6a4SAndroid Build Coastguard Worker if let Some(path) = control_server_path { 1241*bb4ee6a4SAndroid Build Coastguard Worker let server = 1242*bb4ee6a4SAndroid Build Coastguard Worker ControlServer::new(path.to_str().expect("control socket path must be a string")) 1243*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 1244*bb4ee6a4SAndroid Build Coastguard Worker Exit::FailedToCreateControlServer, 1245*bb4ee6a4SAndroid Build Coastguard Worker "failed to create control server", 1246*bb4ee6a4SAndroid Build Coastguard Worker )?; 1247*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 1248*bb4ee6a4SAndroid Build Coastguard Worker .add(server.client_waiting(), Token::VmControlServer) 1249*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 1250*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 1251*bb4ee6a4SAndroid Build Coastguard Worker "failed to add control server to wait context", 1252*bb4ee6a4SAndroid Build Coastguard Worker )?; 1253*bb4ee6a4SAndroid Build Coastguard Worker return Ok(Some(server)); 1254*bb4ee6a4SAndroid Build Coastguard Worker } 1255*bb4ee6a4SAndroid Build Coastguard Worker } 1256*bb4ee6a4SAndroid Build Coastguard Worker Ok::<Option<ControlServer>, anyhow::Error>(None) 1257*bb4ee6a4SAndroid Build Coastguard Worker } 1258*bb4ee6a4SAndroid Build Coastguard Worker 1259*bb4ee6a4SAndroid Build Coastguard Worker fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>( 1260*bb4ee6a4SAndroid Build Coastguard Worker mut guest_os: RunnableLinuxVm<V, Vcpu>, 1261*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator: SystemAllocator, 1262*bb4ee6a4SAndroid Build Coastguard Worker control_tubes: Vec<TaggedControlTube>, 1263*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes: Vec<Tube>, 1264*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes: Vec<Tube>, 1265*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube: RecvTube, 1266*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: SendTube, 1267*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] gpu_control_tube: Option<Tube>, 1268*bb4ee6a4SAndroid Build Coastguard Worker broker_shutdown_evt: Option<Event>, 1269*bb4ee6a4SAndroid Build Coastguard Worker balloon_host_tube: Option<Tube>, 1270*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_host_tube: Option<Tube>, 1271*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes: Vec<Tube>, 1272*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states: Vec<InitialAudioSessionState>, 1273*bb4ee6a4SAndroid Build Coastguard Worker gralloc: RutabagaGralloc, 1274*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] stats: Option<Arc<Mutex<StatisticsCollector>>>, 1275*bb4ee6a4SAndroid Build Coastguard Worker service_pipe_name: Option<String>, 1276*bb4ee6a4SAndroid Build Coastguard Worker memory_size_mb: u64, 1277*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology: bool, 1278*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations: TscSyncMitigations, 1279*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf: bool, 1280*bb4ee6a4SAndroid Build Coastguard Worker mut product_args: RunControlArgs, 1281*bb4ee6a4SAndroid Build Coastguard Worker mut virtio_snd_host_mute_tubes: Vec<Tube>, 1282*bb4ee6a4SAndroid Build Coastguard Worker restore_path: Option<PathBuf>, 1283*bb4ee6a4SAndroid Build Coastguard Worker control_server_path: Option<PathBuf>, 1284*bb4ee6a4SAndroid Build Coastguard Worker force_s2idle: bool, 1285*bb4ee6a4SAndroid Build Coastguard Worker suspended: bool, 1286*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ExitState> { 1287*bb4ee6a4SAndroid Build Coastguard Worker let (ipc_main_loop_tube, proto_main_loop_tube, _service_ipc) = 1288*bb4ee6a4SAndroid Build Coastguard Worker start_service_ipc_listener(service_pipe_name)?; 1289*bb4ee6a4SAndroid Build Coastguard Worker 1290*bb4ee6a4SAndroid Build Coastguard Worker let mut service_vm_state = product::create_service_vm_state(memory_size_mb); 1291*bb4ee6a4SAndroid Build Coastguard Worker 1292*bb4ee6a4SAndroid Build Coastguard Worker let service_audio_states = product::create_service_audio_states_and_send_to_service( 1293*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states, 1294*bb4ee6a4SAndroid Build Coastguard Worker &ipc_main_loop_tube, 1295*bb4ee6a4SAndroid Build Coastguard Worker )?; 1296*bb4ee6a4SAndroid Build Coastguard Worker 1297*bb4ee6a4SAndroid Build Coastguard Worker let sys_allocator_mutex = Arc::new(Mutex::new(sys_allocator)); 1298*bb4ee6a4SAndroid Build Coastguard Worker 1299*bb4ee6a4SAndroid Build Coastguard Worker let exit_evt = Event::new().exit_context(Exit::CreateEvent, "failed to create event")?; 1300*bb4ee6a4SAndroid Build Coastguard Worker let (irq_handler_control, irq_handler_control_for_worker) = Tube::pair().exit_context( 1301*bb4ee6a4SAndroid Build Coastguard Worker Exit::CreateTube, 1302*bb4ee6a4SAndroid Build Coastguard Worker "failed to create IRQ handler control Tube", 1303*bb4ee6a4SAndroid Build Coastguard Worker )?; 1304*bb4ee6a4SAndroid Build Coastguard Worker 1305*bb4ee6a4SAndroid Build Coastguard Worker // Create a separate thread to wait on IRQ events. This is a natural division 1306*bb4ee6a4SAndroid Build Coastguard Worker // because IRQ interrupts have no dependencies on other events, and this lets 1307*bb4ee6a4SAndroid Build Coastguard Worker // us avoid approaching the Windows WaitForMultipleObjects 64-object limit. 1308*bb4ee6a4SAndroid Build Coastguard Worker let irq_join_handle = IrqWaitWorker::start( 1309*bb4ee6a4SAndroid Build Coastguard Worker irq_handler_control_for_worker, 1310*bb4ee6a4SAndroid Build Coastguard Worker guest_os 1311*bb4ee6a4SAndroid Build Coastguard Worker .irq_chip 1312*bb4ee6a4SAndroid Build Coastguard Worker .try_box_clone() 1313*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CloneEvent, "failed to clone irq chip")?, 1314*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes, 1315*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator_mutex.clone(), 1316*bb4ee6a4SAndroid Build Coastguard Worker ); 1317*bb4ee6a4SAndroid Build Coastguard Worker 1318*bb4ee6a4SAndroid Build Coastguard Worker let mut triggers = vec![(vm_evt_rdtube.get_read_notifier(), Token::VmEvent)]; 1319*bb4ee6a4SAndroid Build Coastguard Worker product::push_triggers(&mut triggers, &ipc_main_loop_tube, &proto_main_loop_tube); 1320*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx = WaitContext::build_with(&triggers).exit_context( 1321*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 1322*bb4ee6a4SAndroid Build Coastguard Worker "failed to add trigger to wait context", 1323*bb4ee6a4SAndroid Build Coastguard Worker )?; 1324*bb4ee6a4SAndroid Build Coastguard Worker 1325*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 1326*bb4ee6a4SAndroid Build Coastguard Worker let mut balloon_tube = balloon_host_tube 1327*bb4ee6a4SAndroid Build Coastguard Worker .map(|tube| -> Result<BalloonTube> { 1328*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 1329*bb4ee6a4SAndroid Build Coastguard Worker .add(tube.get_read_notifier(), Token::BalloonTube) 1330*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to add trigger to wait context")?; 1331*bb4ee6a4SAndroid Build Coastguard Worker Ok(BalloonTube::new(tube)) 1332*bb4ee6a4SAndroid Build Coastguard Worker }) 1333*bb4ee6a4SAndroid Build Coastguard Worker .transpose() 1334*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to create balloon tube")?; 1335*bb4ee6a4SAndroid Build Coastguard Worker 1336*bb4ee6a4SAndroid Build Coastguard Worker let (vm_memory_handler_control, vm_memory_handler_control_for_thread) = Tube::pair()?; 1337*bb4ee6a4SAndroid Build Coastguard Worker let vm_memory_handler_thread_join_handle = std::thread::Builder::new() 1338*bb4ee6a4SAndroid Build Coastguard Worker .name("vm_memory_handler_thread".into()) 1339*bb4ee6a4SAndroid Build Coastguard Worker .spawn({ 1340*bb4ee6a4SAndroid Build Coastguard Worker let vm = guest_os.vm.try_clone().context("failed to clone Vm")?; 1341*bb4ee6a4SAndroid Build Coastguard Worker let sys_allocator_mutex = sys_allocator_mutex.clone(); 1342*bb4ee6a4SAndroid Build Coastguard Worker move || { 1343*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_handler_thread( 1344*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes, 1345*bb4ee6a4SAndroid Build Coastguard Worker vm, 1346*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator_mutex, 1347*bb4ee6a4SAndroid Build Coastguard Worker gralloc, 1348*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_handler_control_for_thread, 1349*bb4ee6a4SAndroid Build Coastguard Worker ) 1350*bb4ee6a4SAndroid Build Coastguard Worker } 1351*bb4ee6a4SAndroid Build Coastguard Worker }) 1352*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 1353*bb4ee6a4SAndroid Build Coastguard Worker 1354*bb4ee6a4SAndroid Build Coastguard Worker if let Some(evt) = broker_shutdown_evt.as_ref() { 1355*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx.add(evt, Token::BrokerShutdown).exit_context( 1356*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 1357*bb4ee6a4SAndroid Build Coastguard Worker "failed to add trigger to wait context", 1358*bb4ee6a4SAndroid Build Coastguard Worker )?; 1359*bb4ee6a4SAndroid Build Coastguard Worker } 1360*bb4ee6a4SAndroid Build Coastguard Worker 1361*bb4ee6a4SAndroid Build Coastguard Worker let mut control_tubes = BTreeMap::from_iter(control_tubes.into_iter().enumerate()); 1362*bb4ee6a4SAndroid Build Coastguard Worker let mut next_control_id = control_tubes.len(); 1363*bb4ee6a4SAndroid Build Coastguard Worker for (id, control_tube) in control_tubes.iter() { 1364*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::single_match)] 1365*bb4ee6a4SAndroid Build Coastguard Worker match control_tube { 1366*bb4ee6a4SAndroid Build Coastguard Worker TaggedControlTube::Product(product_tube) => wait_ctx 1367*bb4ee6a4SAndroid Build Coastguard Worker .add( 1368*bb4ee6a4SAndroid Build Coastguard Worker product_tube.get_read_notifier(), 1369*bb4ee6a4SAndroid Build Coastguard Worker Token::VmControl { id: *id }, 1370*bb4ee6a4SAndroid Build Coastguard Worker ) 1371*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 1372*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitContextAdd, 1373*bb4ee6a4SAndroid Build Coastguard Worker "failed to add trigger to wait context", 1374*bb4ee6a4SAndroid Build Coastguard Worker )?, 1375*bb4ee6a4SAndroid Build Coastguard Worker _ => (), 1376*bb4ee6a4SAndroid Build Coastguard Worker } 1377*bb4ee6a4SAndroid Build Coastguard Worker } 1378*bb4ee6a4SAndroid Build Coastguard Worker 1379*bb4ee6a4SAndroid Build Coastguard Worker let (device_ctrl_tube, device_ctrl_resp) = Tube::pair().context("failed to create tube")?; 1380*bb4ee6a4SAndroid Build Coastguard Worker guest_os.devices_thread = match create_devices_worker_thread( 1381*bb4ee6a4SAndroid Build Coastguard Worker guest_os.vm.get_memory().clone(), 1382*bb4ee6a4SAndroid Build Coastguard Worker guest_os.io_bus.clone(), 1383*bb4ee6a4SAndroid Build Coastguard Worker guest_os.mmio_bus.clone(), 1384*bb4ee6a4SAndroid Build Coastguard Worker device_ctrl_resp, 1385*bb4ee6a4SAndroid Build Coastguard Worker ) { 1386*bb4ee6a4SAndroid Build Coastguard Worker Ok(join_handle) => Some(join_handle), 1387*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1388*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!("Failed to start devices thread: {}", e)); 1389*bb4ee6a4SAndroid Build Coastguard Worker } 1390*bb4ee6a4SAndroid Build Coastguard Worker }; 1391*bb4ee6a4SAndroid Build Coastguard Worker 1392*bb4ee6a4SAndroid Build Coastguard Worker let vcpus: Vec<Option<_>> = match guest_os.vcpus.take() { 1393*bb4ee6a4SAndroid Build Coastguard Worker Some(vec) => vec.into_iter().map(|vcpu| Some(vcpu)).collect(), 1394*bb4ee6a4SAndroid Build Coastguard Worker None => iter::repeat_with(|| None) 1395*bb4ee6a4SAndroid Build Coastguard Worker .take(guest_os.vcpu_count) 1396*bb4ee6a4SAndroid Build Coastguard Worker .collect(), 1397*bb4ee6a4SAndroid Build Coastguard Worker }; 1398*bb4ee6a4SAndroid Build Coastguard Worker 1399*bb4ee6a4SAndroid Build Coastguard Worker let anti_tamper_main_thread_tube = spawn_anti_tamper_thread(&wait_ctx); 1400*bb4ee6a4SAndroid Build Coastguard Worker 1401*bb4ee6a4SAndroid Build Coastguard Worker let mut vm_control_server = create_control_server(control_server_path, &wait_ctx)?; 1402*bb4ee6a4SAndroid Build Coastguard Worker 1403*bb4ee6a4SAndroid Build Coastguard Worker let ime_thread = run_ime_thread(&mut product_args, &exit_evt)?; 1404*bb4ee6a4SAndroid Build Coastguard Worker 1405*bb4ee6a4SAndroid Build Coastguard Worker let original_terminal_mode = stdin().set_raw_mode().ok(); 1406*bb4ee6a4SAndroid Build Coastguard Worker 1407*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_boxes: Arc<Mutex<Vec<Box<dyn VcpuArch>>>> = Arc::new(Mutex::new(Vec::new())); 1408*bb4ee6a4SAndroid Build Coastguard Worker let run_mode_arc = Arc::new(VcpuRunMode::default()); 1409*bb4ee6a4SAndroid Build Coastguard Worker 1410*bb4ee6a4SAndroid Build Coastguard Worker let run_mode_state = if suspended { 1411*bb4ee6a4SAndroid Build Coastguard Worker // Sleep devices before creating vcpus. 1412*bb4ee6a4SAndroid Build Coastguard Worker device_ctrl_tube 1413*bb4ee6a4SAndroid Build Coastguard Worker .send(&DeviceControlCommand::SleepDevices) 1414*bb4ee6a4SAndroid Build Coastguard Worker .context("send command to devices control socket")?; 1415*bb4ee6a4SAndroid Build Coastguard Worker match device_ctrl_tube 1416*bb4ee6a4SAndroid Build Coastguard Worker .recv() 1417*bb4ee6a4SAndroid Build Coastguard Worker .context("receive from devices control socket")? 1418*bb4ee6a4SAndroid Build Coastguard Worker { 1419*bb4ee6a4SAndroid Build Coastguard Worker VmResponse::Ok => (), 1420*bb4ee6a4SAndroid Build Coastguard Worker resp => bail!("device sleep failed: {}", resp), 1421*bb4ee6a4SAndroid Build Coastguard Worker } 1422*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.set_and_notify(VmRunMode::Suspending); 1423*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Suspending 1424*bb4ee6a4SAndroid Build Coastguard Worker } else { 1425*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Running 1426*bb4ee6a4SAndroid Build Coastguard Worker }; 1427*bb4ee6a4SAndroid Build Coastguard Worker 1428*bb4ee6a4SAndroid Build Coastguard Worker // If we are restoring from a snapshot, then start suspended. 1429*bb4ee6a4SAndroid Build Coastguard Worker if restore_path.is_some() { 1430*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.set_and_notify(VmRunMode::Suspending); 1431*bb4ee6a4SAndroid Build Coastguard Worker } 1432*bb4ee6a4SAndroid Build Coastguard Worker 1433*bb4ee6a4SAndroid Build Coastguard Worker let (vcpu_threads, vcpu_control_channels) = run_all_vcpus( 1434*bb4ee6a4SAndroid Build Coastguard Worker vcpus, 1435*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.clone(), 1436*bb4ee6a4SAndroid Build Coastguard Worker &guest_os, 1437*bb4ee6a4SAndroid Build Coastguard Worker &exit_evt, 1438*bb4ee6a4SAndroid Build Coastguard Worker &vm_evt_wrtube, 1439*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] 1440*bb4ee6a4SAndroid Build Coastguard Worker &stats, 1441*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology, 1442*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.clone(), 1443*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations, 1444*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf, 1445*bb4ee6a4SAndroid Build Coastguard Worker )?; 1446*bb4ee6a4SAndroid Build Coastguard Worker 1447*bb4ee6a4SAndroid Build Coastguard Worker // See comment on `VmRequest::execute`. 1448*bb4ee6a4SAndroid Build Coastguard Worker let mut suspended_pvclock_state: Option<hypervisor::ClockState> = None; 1449*bb4ee6a4SAndroid Build Coastguard Worker 1450*bb4ee6a4SAndroid Build Coastguard Worker // Restore VM (if applicable). 1451*bb4ee6a4SAndroid Build Coastguard Worker if let Some(path) = restore_path { 1452*bb4ee6a4SAndroid Build Coastguard Worker vm_control::do_restore( 1453*bb4ee6a4SAndroid Build Coastguard Worker &path, 1454*bb4ee6a4SAndroid Build Coastguard Worker |msg| { 1455*bb4ee6a4SAndroid Build Coastguard Worker kick_all_vcpus( 1456*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.as_ref(), 1457*bb4ee6a4SAndroid Build Coastguard Worker &vcpu_control_channels, 1458*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.as_ref(), 1459*bb4ee6a4SAndroid Build Coastguard Worker guest_os.irq_chip.as_ref(), 1460*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1461*bb4ee6a4SAndroid Build Coastguard Worker &pvclock_host_tube, 1462*bb4ee6a4SAndroid Build Coastguard Worker &guest_os.resume_notify_devices, 1463*bb4ee6a4SAndroid Build Coastguard Worker msg, 1464*bb4ee6a4SAndroid Build Coastguard Worker ) 1465*bb4ee6a4SAndroid Build Coastguard Worker }, 1466*bb4ee6a4SAndroid Build Coastguard Worker |msg, index| { 1467*bb4ee6a4SAndroid Build Coastguard Worker kick_vcpu( 1468*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.as_ref(), 1469*bb4ee6a4SAndroid Build Coastguard Worker &vcpu_control_channels, 1470*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.as_ref(), 1471*bb4ee6a4SAndroid Build Coastguard Worker guest_os.irq_chip.as_ref(), 1472*bb4ee6a4SAndroid Build Coastguard Worker index, 1473*bb4ee6a4SAndroid Build Coastguard Worker msg, 1474*bb4ee6a4SAndroid Build Coastguard Worker ) 1475*bb4ee6a4SAndroid Build Coastguard Worker }, 1476*bb4ee6a4SAndroid Build Coastguard Worker &irq_handler_control, 1477*bb4ee6a4SAndroid Build Coastguard Worker &device_ctrl_tube, 1478*bb4ee6a4SAndroid Build Coastguard Worker guest_os.vcpu_count, 1479*bb4ee6a4SAndroid Build Coastguard Worker |image| { 1480*bb4ee6a4SAndroid Build Coastguard Worker guest_os 1481*bb4ee6a4SAndroid Build Coastguard Worker .irq_chip 1482*bb4ee6a4SAndroid Build Coastguard Worker .try_box_clone()? 1483*bb4ee6a4SAndroid Build Coastguard Worker .restore(image, guest_os.vcpu_count) 1484*bb4ee6a4SAndroid Build Coastguard Worker }, 1485*bb4ee6a4SAndroid Build Coastguard Worker /* require_encrypted= */ false, 1486*bb4ee6a4SAndroid Build Coastguard Worker &mut suspended_pvclock_state, 1487*bb4ee6a4SAndroid Build Coastguard Worker )?; 1488*bb4ee6a4SAndroid Build Coastguard Worker // Allow the vCPUs to start for real. 1489*bb4ee6a4SAndroid Build Coastguard Worker kick_all_vcpus( 1490*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.as_ref(), 1491*bb4ee6a4SAndroid Build Coastguard Worker &vcpu_control_channels, 1492*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.as_ref(), 1493*bb4ee6a4SAndroid Build Coastguard Worker guest_os.irq_chip.as_ref(), 1494*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1495*bb4ee6a4SAndroid Build Coastguard Worker &pvclock_host_tube, 1496*bb4ee6a4SAndroid Build Coastguard Worker &guest_os.resume_notify_devices, 1497*bb4ee6a4SAndroid Build Coastguard Worker // Other platforms (unix) have multiple modes they could start in (e.g. starting for 1498*bb4ee6a4SAndroid Build Coastguard Worker // guest kernel debugging, etc). If/when we support those modes on Windows, we'll need 1499*bb4ee6a4SAndroid Build Coastguard Worker // to enter that mode here rather than VmRunMode::Running. 1500*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::RunState(run_mode_state), 1501*bb4ee6a4SAndroid Build Coastguard Worker ); 1502*bb4ee6a4SAndroid Build Coastguard Worker } 1503*bb4ee6a4SAndroid Build Coastguard Worker 1504*bb4ee6a4SAndroid Build Coastguard Worker let mut exit_state = ExitState::Stop; 1505*bb4ee6a4SAndroid Build Coastguard Worker let mut region_state: VmMemoryRegionState = Default::default(); 1506*bb4ee6a4SAndroid Build Coastguard Worker 1507*bb4ee6a4SAndroid Build Coastguard Worker 'poll: loop { 1508*bb4ee6a4SAndroid Build Coastguard Worker let events = { 1509*bb4ee6a4SAndroid Build Coastguard Worker match wait_ctx.wait() { 1510*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v, 1511*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1512*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to wait: {}", e); 1513*bb4ee6a4SAndroid Build Coastguard Worker break; 1514*bb4ee6a4SAndroid Build Coastguard Worker } 1515*bb4ee6a4SAndroid Build Coastguard Worker } 1516*bb4ee6a4SAndroid Build Coastguard Worker }; 1517*bb4ee6a4SAndroid Build Coastguard Worker 1518*bb4ee6a4SAndroid Build Coastguard Worker let mut vm_control_ids_to_remove = Vec::new(); 1519*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) { 1520*bb4ee6a4SAndroid Build Coastguard Worker let state = handle_readable_event( 1521*bb4ee6a4SAndroid Build Coastguard Worker event, 1522*bb4ee6a4SAndroid Build Coastguard Worker &mut vm_control_ids_to_remove, 1523*bb4ee6a4SAndroid Build Coastguard Worker &mut next_control_id, 1524*bb4ee6a4SAndroid Build Coastguard Worker &mut service_vm_state, 1525*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes.as_slice(), 1526*bb4ee6a4SAndroid Build Coastguard Worker ipc_main_loop_tube.as_ref(), 1527*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 1528*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube.as_ref(), 1529*bb4ee6a4SAndroid Build Coastguard Worker &vm_evt_rdtube, 1530*bb4ee6a4SAndroid Build Coastguard Worker &mut control_tubes, 1531*bb4ee6a4SAndroid Build Coastguard Worker &mut guest_os, 1532*bb4ee6a4SAndroid Build Coastguard Worker &sys_allocator_mutex, 1533*bb4ee6a4SAndroid Build Coastguard Worker &mut virtio_snd_host_mute_tubes, 1534*bb4ee6a4SAndroid Build Coastguard Worker proto_main_loop_tube.as_ref(), 1535*bb4ee6a4SAndroid Build Coastguard Worker &anti_tamper_main_thread_tube, 1536*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")] 1537*bb4ee6a4SAndroid Build Coastguard Worker balloon_tube.as_mut(), 1538*bb4ee6a4SAndroid Build Coastguard Worker memory_size_mb, 1539*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.as_ref(), 1540*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1541*bb4ee6a4SAndroid Build Coastguard Worker &pvclock_host_tube, 1542*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.as_ref(), 1543*bb4ee6a4SAndroid Build Coastguard Worker &mut region_state, 1544*bb4ee6a4SAndroid Build Coastguard Worker vm_control_server.as_mut(), 1545*bb4ee6a4SAndroid Build Coastguard Worker &irq_handler_control, 1546*bb4ee6a4SAndroid Build Coastguard Worker &device_ctrl_tube, 1547*bb4ee6a4SAndroid Build Coastguard Worker &wait_ctx, 1548*bb4ee6a4SAndroid Build Coastguard Worker force_s2idle, 1549*bb4ee6a4SAndroid Build Coastguard Worker &vcpu_control_channels, 1550*bb4ee6a4SAndroid Build Coastguard Worker &mut suspended_pvclock_state, 1551*bb4ee6a4SAndroid Build Coastguard Worker )?; 1552*bb4ee6a4SAndroid Build Coastguard Worker if let Some(state) = state { 1553*bb4ee6a4SAndroid Build Coastguard Worker exit_state = state; 1554*bb4ee6a4SAndroid Build Coastguard Worker break 'poll; 1555*bb4ee6a4SAndroid Build Coastguard Worker } 1556*bb4ee6a4SAndroid Build Coastguard Worker } 1557*bb4ee6a4SAndroid Build Coastguard Worker 1558*bb4ee6a4SAndroid Build Coastguard Worker remove_closed_tubes(&wait_ctx, &mut control_tubes, vm_control_ids_to_remove)?; 1559*bb4ee6a4SAndroid Build Coastguard Worker } 1560*bb4ee6a4SAndroid Build Coastguard Worker 1561*bb4ee6a4SAndroid Build Coastguard Worker info!("run_control poll loop completed, forcing vCPUs to exit..."); 1562*bb4ee6a4SAndroid Build Coastguard Worker 1563*bb4ee6a4SAndroid Build Coastguard Worker // VCPU threads MUST see the VmRunMode flag, otherwise they may re-enter the VM. 1564*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.set_and_notify(VmRunMode::Exiting); 1565*bb4ee6a4SAndroid Build Coastguard Worker 1566*bb4ee6a4SAndroid Build Coastguard Worker // Force all vcpus to exit from the hypervisor 1567*bb4ee6a4SAndroid Build Coastguard Worker for vcpu in vcpu_boxes.lock().iter() { 1568*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_immediate_exit(true); 1569*bb4ee6a4SAndroid Build Coastguard Worker } 1570*bb4ee6a4SAndroid Build Coastguard Worker 1571*bb4ee6a4SAndroid Build Coastguard Worker let mut res = Ok(exit_state); 1572*bb4ee6a4SAndroid Build Coastguard Worker guest_os.irq_chip.kick_halted_vcpus(); 1573*bb4ee6a4SAndroid Build Coastguard Worker let _ = exit_evt.signal(); 1574*bb4ee6a4SAndroid Build Coastguard Worker 1575*bb4ee6a4SAndroid Build Coastguard Worker if guest_os.devices_thread.is_some() { 1576*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = device_ctrl_tube.send(&DeviceControlCommand::Exit) { 1577*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to stop device control loop: {}", e); 1578*bb4ee6a4SAndroid Build Coastguard Worker }; 1579*bb4ee6a4SAndroid Build Coastguard Worker if let Some(thread) = guest_os.devices_thread.take() { 1580*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = thread.join() { 1581*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to exit devices thread: {:?}", e); 1582*bb4ee6a4SAndroid Build Coastguard Worker } 1583*bb4ee6a4SAndroid Build Coastguard Worker } 1584*bb4ee6a4SAndroid Build Coastguard Worker } 1585*bb4ee6a4SAndroid Build Coastguard Worker 1586*bb4ee6a4SAndroid Build Coastguard Worker // Shut down the VM memory handler thread. 1587*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = vm_memory_handler_control.send(&VmMemoryHandlerRequest::Exit) { 1588*bb4ee6a4SAndroid Build Coastguard Worker error!( 1589*bb4ee6a4SAndroid Build Coastguard Worker "failed to request exit from VM memory handler thread: {}", 1590*bb4ee6a4SAndroid Build Coastguard Worker e 1591*bb4ee6a4SAndroid Build Coastguard Worker ); 1592*bb4ee6a4SAndroid Build Coastguard Worker } 1593*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = vm_memory_handler_thread_join_handle.join() { 1594*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to exit VM Memory handler thread: {:?}", e); 1595*bb4ee6a4SAndroid Build Coastguard Worker } 1596*bb4ee6a4SAndroid Build Coastguard Worker 1597*bb4ee6a4SAndroid Build Coastguard Worker // Shut down the IRQ handler thread. 1598*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = irq_handler_control.send(&IrqHandlerRequest::Exit) { 1599*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to request exit from IRQ handler thread: {}", e); 1600*bb4ee6a4SAndroid Build Coastguard Worker } 1601*bb4ee6a4SAndroid Build Coastguard Worker 1602*bb4ee6a4SAndroid Build Coastguard Worker // Ensure any child threads have ended by sending the Exit vm event (possibly again) to ensure 1603*bb4ee6a4SAndroid Build Coastguard Worker // their run loops are aborted. 1604*bb4ee6a4SAndroid Build Coastguard Worker let _ = vm_evt_wrtube.send::<VmEventType>(&VmEventType::Exit); 1605*bb4ee6a4SAndroid Build Coastguard Worker for (i, thread) in vcpu_threads.into_iter().enumerate() { 1606*bb4ee6a4SAndroid Build Coastguard Worker // wait till all the threads exit, so that guest_os.vm arc memory count is down to 1. 1607*bb4ee6a4SAndroid Build Coastguard Worker // otherwise, we will hit a memory leak if we force kill the thread with terminate. 1608*bb4ee6a4SAndroid Build Coastguard Worker match thread.join() { 1609*bb4ee6a4SAndroid Build Coastguard Worker Ok(Err(e)) => { 1610*bb4ee6a4SAndroid Build Coastguard Worker error!("vcpu thread {} exited with an error: {}", i, e); 1611*bb4ee6a4SAndroid Build Coastguard Worker res = Err(e); 1612*bb4ee6a4SAndroid Build Coastguard Worker } 1613*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 1614*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => error!("vcpu thread {} panicked: {:?}", i, e), 1615*bb4ee6a4SAndroid Build Coastguard Worker } 1616*bb4ee6a4SAndroid Build Coastguard Worker } 1617*bb4ee6a4SAndroid Build Coastguard Worker 1618*bb4ee6a4SAndroid Build Coastguard Worker info!("vCPU threads have exited."); 1619*bb4ee6a4SAndroid Build Coastguard Worker 1620*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ime) = ime_thread { 1621*bb4ee6a4SAndroid Build Coastguard Worker match ime.join() { 1622*bb4ee6a4SAndroid Build Coastguard Worker Ok(Err(e)) => { 1623*bb4ee6a4SAndroid Build Coastguard Worker error!("ime thread exited with an error: {}", e); 1624*bb4ee6a4SAndroid Build Coastguard Worker if res.is_ok() { 1625*bb4ee6a4SAndroid Build Coastguard Worker // Prioritize past errors, but return this error if it is unique, otherwise just 1626*bb4ee6a4SAndroid Build Coastguard Worker // log it. 1627*bb4ee6a4SAndroid Build Coastguard Worker res = Err(e) 1628*bb4ee6a4SAndroid Build Coastguard Worker } 1629*bb4ee6a4SAndroid Build Coastguard Worker } 1630*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 1631*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => error!("ime thread panicked: {:?}", e), 1632*bb4ee6a4SAndroid Build Coastguard Worker } 1633*bb4ee6a4SAndroid Build Coastguard Worker } 1634*bb4ee6a4SAndroid Build Coastguard Worker info!("IME thread has exited."); 1635*bb4ee6a4SAndroid Build Coastguard Worker 1636*bb4ee6a4SAndroid Build Coastguard Worker // This cancels all the outstanding and any future blocking operations. 1637*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/196911556): Shutdown executor for cleaner shutdown. Given we are using global, for a 1638*bb4ee6a4SAndroid Build Coastguard Worker // cleaner shutdown we have to call disarm so that all the incoming requests are run and are 1639*bb4ee6a4SAndroid Build Coastguard Worker // cancelled. If we call shutdown all blocking threads will go away and incoming operations 1640*bb4ee6a4SAndroid Build Coastguard Worker // won't be scheduled to run and will be dropped leading to panic. I think ideal place to call 1641*bb4ee6a4SAndroid Build Coastguard Worker // shutdown is when we drop non-global executor. 1642*bb4ee6a4SAndroid Build Coastguard Worker cros_async::unblock_disarm(); 1643*bb4ee6a4SAndroid Build Coastguard Worker info!("blocking async pool has shut down."); 1644*bb4ee6a4SAndroid Build Coastguard Worker 1645*bb4ee6a4SAndroid Build Coastguard Worker let _ = irq_join_handle.join(); 1646*bb4ee6a4SAndroid Build Coastguard Worker info!("IrqWaitWorker has shut down."); 1647*bb4ee6a4SAndroid Build Coastguard Worker 1648*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] 1649*bb4ee6a4SAndroid Build Coastguard Worker if let Some(stats) = stats { 1650*bb4ee6a4SAndroid Build Coastguard Worker println!("Statistics Collected:\n{}", stats.lock()); 1651*bb4ee6a4SAndroid Build Coastguard Worker println!("Statistics JSON:\n{}", stats.lock().json()); 1652*bb4ee6a4SAndroid Build Coastguard Worker } 1653*bb4ee6a4SAndroid Build Coastguard Worker 1654*bb4ee6a4SAndroid Build Coastguard Worker if let Some(mode) = original_terminal_mode { 1655*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = stdin().restore_mode(mode) { 1656*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to restore terminal mode: {}", e); 1657*bb4ee6a4SAndroid Build Coastguard Worker } 1658*bb4ee6a4SAndroid Build Coastguard Worker } 1659*bb4ee6a4SAndroid Build Coastguard Worker 1660*bb4ee6a4SAndroid Build Coastguard Worker // Explicitly drop the VM structure here to allow the devices to clean up before the 1661*bb4ee6a4SAndroid Build Coastguard Worker // control tubes are closed when this function exits. 1662*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(guest_os); 1663*bb4ee6a4SAndroid Build Coastguard Worker 1664*bb4ee6a4SAndroid Build Coastguard Worker info!("guest_os dropped, run_control is done."); 1665*bb4ee6a4SAndroid Build Coastguard Worker 1666*bb4ee6a4SAndroid Build Coastguard Worker res 1667*bb4ee6a4SAndroid Build Coastguard Worker } 1668*bb4ee6a4SAndroid Build Coastguard Worker 1669*bb4ee6a4SAndroid Build Coastguard Worker /// Remove Tubes that have been closed from the WaitContext. 1670*bb4ee6a4SAndroid Build Coastguard Worker fn remove_closed_tubes<T, U>( 1671*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &WaitContext<T>, 1672*bb4ee6a4SAndroid Build Coastguard Worker tubes: &mut BTreeMap<usize, U>, 1673*bb4ee6a4SAndroid Build Coastguard Worker mut tube_ids_to_remove: Vec<usize>, 1674*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> 1675*bb4ee6a4SAndroid Build Coastguard Worker where 1676*bb4ee6a4SAndroid Build Coastguard Worker T: EventToken, 1677*bb4ee6a4SAndroid Build Coastguard Worker U: ReadNotifier + CloseNotifier, 1678*bb4ee6a4SAndroid Build Coastguard Worker { 1679*bb4ee6a4SAndroid Build Coastguard Worker tube_ids_to_remove.dedup(); 1680*bb4ee6a4SAndroid Build Coastguard Worker for id in tube_ids_to_remove { 1681*bb4ee6a4SAndroid Build Coastguard Worker if let Some(socket) = tubes.remove(&id) { 1682*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx 1683*bb4ee6a4SAndroid Build Coastguard Worker .delete(socket.get_read_notifier()) 1684*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to remove descriptor from wait context")?; 1685*bb4ee6a4SAndroid Build Coastguard Worker 1686*bb4ee6a4SAndroid Build Coastguard Worker // There may be a close notifier registered for this Tube. If there isn't one 1687*bb4ee6a4SAndroid Build Coastguard Worker // registered, we just ignore the error. 1688*bb4ee6a4SAndroid Build Coastguard Worker let _ = wait_ctx.delete(socket.get_close_notifier()); 1689*bb4ee6a4SAndroid Build Coastguard Worker } 1690*bb4ee6a4SAndroid Build Coastguard Worker } 1691*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 1692*bb4ee6a4SAndroid Build Coastguard Worker } 1693*bb4ee6a4SAndroid Build Coastguard Worker 1694*bb4ee6a4SAndroid Build Coastguard Worker /// Sends a message to all VCPUs. 1695*bb4ee6a4SAndroid Build Coastguard Worker fn kick_all_vcpus( 1696*bb4ee6a4SAndroid Build Coastguard Worker run_mode: &VcpuRunMode, 1697*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_channels: &[mpsc::Sender<VcpuControl>], 1698*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: &Mutex<Vec<Box<dyn VcpuArch>>>, 1699*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &dyn IrqChipArch, 1700*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_host_tube: &Option<Tube>, 1701*bb4ee6a4SAndroid Build Coastguard Worker resume_notify_devices: &[Arc<Mutex<dyn BusResumeDevice>>], 1702*bb4ee6a4SAndroid Build Coastguard Worker msg: VcpuControl, 1703*bb4ee6a4SAndroid Build Coastguard Worker ) { 1704*bb4ee6a4SAndroid Build Coastguard Worker // On Windows, we handle run mode switching directly rather than delegating to the VCPU thread 1705*bb4ee6a4SAndroid Build Coastguard Worker // like unix does. 1706*bb4ee6a4SAndroid Build Coastguard Worker match &msg { 1707*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::RunState(VmRunMode::Suspending) => { 1708*bb4ee6a4SAndroid Build Coastguard Worker suspend_all_vcpus( 1709*bb4ee6a4SAndroid Build Coastguard Worker run_mode, 1710*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes, 1711*bb4ee6a4SAndroid Build Coastguard Worker irq_chip, 1712*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1713*bb4ee6a4SAndroid Build Coastguard Worker pvclock_host_tube, 1714*bb4ee6a4SAndroid Build Coastguard Worker ); 1715*bb4ee6a4SAndroid Build Coastguard Worker return; 1716*bb4ee6a4SAndroid Build Coastguard Worker } 1717*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::RunState(VmRunMode::Running) => { 1718*bb4ee6a4SAndroid Build Coastguard Worker for device in resume_notify_devices { 1719*bb4ee6a4SAndroid Build Coastguard Worker device.lock().resume_imminent(); 1720*bb4ee6a4SAndroid Build Coastguard Worker } 1721*bb4ee6a4SAndroid Build Coastguard Worker resume_all_vcpus( 1722*bb4ee6a4SAndroid Build Coastguard Worker run_mode, 1723*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes, 1724*bb4ee6a4SAndroid Build Coastguard Worker irq_chip, 1725*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1726*bb4ee6a4SAndroid Build Coastguard Worker pvclock_host_tube, 1727*bb4ee6a4SAndroid Build Coastguard Worker ); 1728*bb4ee6a4SAndroid Build Coastguard Worker return; 1729*bb4ee6a4SAndroid Build Coastguard Worker } 1730*bb4ee6a4SAndroid Build Coastguard Worker _ => (), 1731*bb4ee6a4SAndroid Build Coastguard Worker } 1732*bb4ee6a4SAndroid Build Coastguard Worker 1733*bb4ee6a4SAndroid Build Coastguard Worker // For non RunState commands, we dispatch just like unix would. 1734*bb4ee6a4SAndroid Build Coastguard Worker for vcpu in vcpu_control_channels { 1735*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = vcpu.send(msg.clone()) { 1736*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send VcpuControl message: {}", e); 1737*bb4ee6a4SAndroid Build Coastguard Worker } 1738*bb4ee6a4SAndroid Build Coastguard Worker } 1739*bb4ee6a4SAndroid Build Coastguard Worker 1740*bb4ee6a4SAndroid Build Coastguard Worker // Now that we've sent a message, we need VCPUs to exit so they can process it. 1741*bb4ee6a4SAndroid Build Coastguard Worker for vcpu in vcpu_boxes.lock().iter() { 1742*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_immediate_exit(true); 1743*bb4ee6a4SAndroid Build Coastguard Worker } 1744*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.kick_halted_vcpus(); 1745*bb4ee6a4SAndroid Build Coastguard Worker 1746*bb4ee6a4SAndroid Build Coastguard Worker // If the VCPU isn't running, we have to notify the run_mode condvar to wake it so it processes 1747*bb4ee6a4SAndroid Build Coastguard Worker // the control message. 1748*bb4ee6a4SAndroid Build Coastguard Worker let current_run_mode = run_mode.get_mode(); 1749*bb4ee6a4SAndroid Build Coastguard Worker if current_run_mode != VmRunMode::Running { 1750*bb4ee6a4SAndroid Build Coastguard Worker run_mode.set_and_notify(current_run_mode); 1751*bb4ee6a4SAndroid Build Coastguard Worker } 1752*bb4ee6a4SAndroid Build Coastguard Worker } 1753*bb4ee6a4SAndroid Build Coastguard Worker 1754*bb4ee6a4SAndroid Build Coastguard Worker /// Sends a message to a single VCPU. On Windows, `VcpuControl::RunState` cannot be sent to a single 1755*bb4ee6a4SAndroid Build Coastguard Worker /// VCPU. 1756*bb4ee6a4SAndroid Build Coastguard Worker fn kick_vcpu( 1757*bb4ee6a4SAndroid Build Coastguard Worker run_mode: &VcpuRunMode, 1758*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_channels: &[mpsc::Sender<VcpuControl>], 1759*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: &Mutex<Vec<Box<dyn VcpuArch>>>, 1760*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &dyn IrqChipArch, 1761*bb4ee6a4SAndroid Build Coastguard Worker index: usize, 1762*bb4ee6a4SAndroid Build Coastguard Worker msg: VcpuControl, 1763*bb4ee6a4SAndroid Build Coastguard Worker ) { 1764*bb4ee6a4SAndroid Build Coastguard Worker assert!( 1765*bb4ee6a4SAndroid Build Coastguard Worker !matches!(msg, VcpuControl::RunState(_)), 1766*bb4ee6a4SAndroid Build Coastguard Worker "Windows does not support RunState changes on a per VCPU basis" 1767*bb4ee6a4SAndroid Build Coastguard Worker ); 1768*bb4ee6a4SAndroid Build Coastguard Worker 1769*bb4ee6a4SAndroid Build Coastguard Worker let vcpu = vcpu_control_channels 1770*bb4ee6a4SAndroid Build Coastguard Worker .get(index) 1771*bb4ee6a4SAndroid Build Coastguard Worker .expect("invalid vcpu index specified"); 1772*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = vcpu.send(msg) { 1773*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to send VcpuControl message: {}", e); 1774*bb4ee6a4SAndroid Build Coastguard Worker } 1775*bb4ee6a4SAndroid Build Coastguard Worker 1776*bb4ee6a4SAndroid Build Coastguard Worker // Now that we've sent a message, we need the VCPU to exit so it can 1777*bb4ee6a4SAndroid Build Coastguard Worker // process the message. 1778*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes 1779*bb4ee6a4SAndroid Build Coastguard Worker .lock() 1780*bb4ee6a4SAndroid Build Coastguard Worker .get(index) 1781*bb4ee6a4SAndroid Build Coastguard Worker .expect("invalid vcpu index specified") 1782*bb4ee6a4SAndroid Build Coastguard Worker .set_immediate_exit(true); 1783*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.kick_halted_vcpus(); 1784*bb4ee6a4SAndroid Build Coastguard Worker 1785*bb4ee6a4SAndroid Build Coastguard Worker // If the VCPU isn't running, we have to notify the run_mode condvar to wake it so it processes 1786*bb4ee6a4SAndroid Build Coastguard Worker // the control message. (Technically this wakes all VCPUs, but those without messages will go 1787*bb4ee6a4SAndroid Build Coastguard Worker // back to sleep.) 1788*bb4ee6a4SAndroid Build Coastguard Worker let current_run_mode = run_mode.get_mode(); 1789*bb4ee6a4SAndroid Build Coastguard Worker if current_run_mode != VmRunMode::Running { 1790*bb4ee6a4SAndroid Build Coastguard Worker run_mode.set_and_notify(current_run_mode); 1791*bb4ee6a4SAndroid Build Coastguard Worker } 1792*bb4ee6a4SAndroid Build Coastguard Worker } 1793*bb4ee6a4SAndroid Build Coastguard Worker 1794*bb4ee6a4SAndroid Build Coastguard Worker /// Suspends all VCPUs. The VM will be effectively frozen in time once this function is called, 1795*bb4ee6a4SAndroid Build Coastguard Worker /// though devices on the host will continue to run. 1796*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn suspend_all_vcpus( 1797*bb4ee6a4SAndroid Build Coastguard Worker run_mode: &VcpuRunMode, 1798*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: &Mutex<Vec<Box<dyn VcpuArch>>>, 1799*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &dyn IrqChipArch, 1800*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_host_tube: &Option<Tube>, 1801*bb4ee6a4SAndroid Build Coastguard Worker ) { 1802*bb4ee6a4SAndroid Build Coastguard Worker // VCPU threads MUST see the VmRunMode::Suspending flag first, otherwise 1803*bb4ee6a4SAndroid Build Coastguard Worker // they may re-enter the VM. 1804*bb4ee6a4SAndroid Build Coastguard Worker run_mode.set_and_notify(VmRunMode::Suspending); 1805*bb4ee6a4SAndroid Build Coastguard Worker 1806*bb4ee6a4SAndroid Build Coastguard Worker // Force all vcpus to exit from the hypervisor 1807*bb4ee6a4SAndroid Build Coastguard Worker for vcpu in vcpu_boxes.lock().iter() { 1808*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_immediate_exit(true); 1809*bb4ee6a4SAndroid Build Coastguard Worker } 1810*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.kick_halted_vcpus(); 1811*bb4ee6a4SAndroid Build Coastguard Worker 1812*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1813*bb4ee6a4SAndroid Build Coastguard Worker handle_pvclock_request(pvclock_host_tube, PvClockCommand::Suspend) 1814*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| error!("Error handling pvclock suspend: {:?}", e)); 1815*bb4ee6a4SAndroid Build Coastguard Worker } 1816*bb4ee6a4SAndroid Build Coastguard Worker 1817*bb4ee6a4SAndroid Build Coastguard Worker /// Resumes all VCPUs. 1818*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn resume_all_vcpus( 1819*bb4ee6a4SAndroid Build Coastguard Worker run_mode: &VcpuRunMode, 1820*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: &Mutex<Vec<Box<dyn VcpuArch>>>, 1821*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &dyn IrqChipArch, 1822*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] pvclock_host_tube: &Option<Tube>, 1823*bb4ee6a4SAndroid Build Coastguard Worker ) { 1824*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 1825*bb4ee6a4SAndroid Build Coastguard Worker handle_pvclock_request(pvclock_host_tube, PvClockCommand::Resume) 1826*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| error!("Error handling pvclock resume: {:?}", e)); 1827*bb4ee6a4SAndroid Build Coastguard Worker 1828*bb4ee6a4SAndroid Build Coastguard Worker // Make sure any immediate exit bits are disabled 1829*bb4ee6a4SAndroid Build Coastguard Worker for vcpu in vcpu_boxes.lock().iter() { 1830*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_immediate_exit(false); 1831*bb4ee6a4SAndroid Build Coastguard Worker } 1832*bb4ee6a4SAndroid Build Coastguard Worker 1833*bb4ee6a4SAndroid Build Coastguard Worker run_mode.set_and_notify(VmRunMode::Running); 1834*bb4ee6a4SAndroid Build Coastguard Worker } 1835*bb4ee6a4SAndroid Build Coastguard Worker 1836*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 1837*bb4ee6a4SAndroid Build Coastguard Worker const GVM_MINIMUM_VERSION: GvmVersion = GvmVersion { 1838*bb4ee6a4SAndroid Build Coastguard Worker major: 1, 1839*bb4ee6a4SAndroid Build Coastguard Worker minor: 4, 1840*bb4ee6a4SAndroid Build Coastguard Worker patch: 1, 1841*bb4ee6a4SAndroid Build Coastguard Worker }; 1842*bb4ee6a4SAndroid Build Coastguard Worker 1843*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 1844*bb4ee6a4SAndroid Build Coastguard Worker fn create_gvm_vm(gvm: Gvm, mem: GuestMemory) -> Result<GvmVm> { 1845*bb4ee6a4SAndroid Build Coastguard Worker match gvm.get_full_version() { 1846*bb4ee6a4SAndroid Build Coastguard Worker Ok(version) => { 1847*bb4ee6a4SAndroid Build Coastguard Worker if version < GVM_MINIMUM_VERSION { 1848*bb4ee6a4SAndroid Build Coastguard Worker error!( 1849*bb4ee6a4SAndroid Build Coastguard Worker "GVM version {} is below minimum version {}", 1850*bb4ee6a4SAndroid Build Coastguard Worker version, GVM_MINIMUM_VERSION 1851*bb4ee6a4SAndroid Build Coastguard Worker ); 1852*bb4ee6a4SAndroid Build Coastguard Worker return Err(base::Error::new(libc::ENXIO).into()); 1853*bb4ee6a4SAndroid Build Coastguard Worker } else { 1854*bb4ee6a4SAndroid Build Coastguard Worker info!("Using GVM version {}.", version) 1855*bb4ee6a4SAndroid Build Coastguard Worker } 1856*bb4ee6a4SAndroid Build Coastguard Worker } 1857*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 1858*bb4ee6a4SAndroid Build Coastguard Worker error!("unable to determine gvm version: {}", e); 1859*bb4ee6a4SAndroid Build Coastguard Worker return Err(base::Error::new(libc::ENXIO).into()); 1860*bb4ee6a4SAndroid Build Coastguard Worker } 1861*bb4ee6a4SAndroid Build Coastguard Worker } 1862*bb4ee6a4SAndroid Build Coastguard Worker let vm = GvmVm::new(&gvm, mem)?; 1863*bb4ee6a4SAndroid Build Coastguard Worker Ok(vm) 1864*bb4ee6a4SAndroid Build Coastguard Worker } 1865*bb4ee6a4SAndroid Build Coastguard Worker 1866*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 1867*bb4ee6a4SAndroid Build Coastguard Worker fn create_haxm_vm( 1868*bb4ee6a4SAndroid Build Coastguard Worker haxm: Haxm, 1869*bb4ee6a4SAndroid Build Coastguard Worker mem: GuestMemory, 1870*bb4ee6a4SAndroid Build Coastguard Worker kernel_log_file: &Option<String>, 1871*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<HaxmVm> { 1872*bb4ee6a4SAndroid Build Coastguard Worker let vm = HaxmVm::new(&haxm, mem)?; 1873*bb4ee6a4SAndroid Build Coastguard Worker if let Some(path) = kernel_log_file { 1874*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::haxm::HAX_CAP_VM_LOG; 1875*bb4ee6a4SAndroid Build Coastguard Worker if vm.check_raw_capability(HAX_CAP_VM_LOG) { 1876*bb4ee6a4SAndroid Build Coastguard Worker match vm.register_log_file(path) { 1877*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 1878*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => match e.errno() { 1879*bb4ee6a4SAndroid Build Coastguard Worker libc::E2BIG => { 1880*bb4ee6a4SAndroid Build Coastguard Worker error!( 1881*bb4ee6a4SAndroid Build Coastguard Worker "kernel_log_file path is too long, kernel log file will not be written" 1882*bb4ee6a4SAndroid Build Coastguard Worker ); 1883*bb4ee6a4SAndroid Build Coastguard Worker } 1884*bb4ee6a4SAndroid Build Coastguard Worker _ => return Err(e.into()), 1885*bb4ee6a4SAndroid Build Coastguard Worker }, 1886*bb4ee6a4SAndroid Build Coastguard Worker } 1887*bb4ee6a4SAndroid Build Coastguard Worker } else { 1888*bb4ee6a4SAndroid Build Coastguard Worker warn!( 1889*bb4ee6a4SAndroid Build Coastguard Worker "kernel_log_file specified but this version of HAXM does not support kernel log \ 1890*bb4ee6a4SAndroid Build Coastguard Worker files" 1891*bb4ee6a4SAndroid Build Coastguard Worker ); 1892*bb4ee6a4SAndroid Build Coastguard Worker } 1893*bb4ee6a4SAndroid Build Coastguard Worker } 1894*bb4ee6a4SAndroid Build Coastguard Worker Ok(vm) 1895*bb4ee6a4SAndroid Build Coastguard Worker } 1896*bb4ee6a4SAndroid Build Coastguard Worker 1897*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 1898*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 1899*bb4ee6a4SAndroid Build Coastguard Worker fn create_whpx_vm( 1900*bb4ee6a4SAndroid Build Coastguard Worker whpx: Whpx, 1901*bb4ee6a4SAndroid Build Coastguard Worker mem: GuestMemory, 1902*bb4ee6a4SAndroid Build Coastguard Worker cpu_count: usize, 1903*bb4ee6a4SAndroid Build Coastguard Worker no_smt: bool, 1904*bb4ee6a4SAndroid Build Coastguard Worker apic_emulation: bool, 1905*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf: bool, 1906*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: SendTube, 1907*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<WhpxVm> { 1908*bb4ee6a4SAndroid Build Coastguard Worker let cpu_config = hypervisor::CpuConfigX86_64::new( 1909*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf, 1910*bb4ee6a4SAndroid Build Coastguard Worker false, /* host_cpu_topology */ 1911*bb4ee6a4SAndroid Build Coastguard Worker false, /* enable_hwp */ 1912*bb4ee6a4SAndroid Build Coastguard Worker no_smt, 1913*bb4ee6a4SAndroid Build Coastguard Worker false, /* itmt */ 1914*bb4ee6a4SAndroid Build Coastguard Worker None, /* hybrid_type */ 1915*bb4ee6a4SAndroid Build Coastguard Worker ); 1916*bb4ee6a4SAndroid Build Coastguard Worker 1917*bb4ee6a4SAndroid Build Coastguard Worker // context for non-cpu-specific cpuid results 1918*bb4ee6a4SAndroid Build Coastguard Worker let ctx = CpuIdContext::new( 1919*bb4ee6a4SAndroid Build Coastguard Worker 0, 1920*bb4ee6a4SAndroid Build Coastguard Worker cpu_count, 1921*bb4ee6a4SAndroid Build Coastguard Worker None, 1922*bb4ee6a4SAndroid Build Coastguard Worker cpu_config, 1923*bb4ee6a4SAndroid Build Coastguard Worker whpx.check_capability(HypervisorCap::CalibratedTscLeafRequired), 1924*bb4ee6a4SAndroid Build Coastguard Worker __cpuid_count, 1925*bb4ee6a4SAndroid Build Coastguard Worker __cpuid, 1926*bb4ee6a4SAndroid Build Coastguard Worker ); 1927*bb4ee6a4SAndroid Build Coastguard Worker 1928*bb4ee6a4SAndroid Build Coastguard Worker // Get all cpuid entries that we should pre-set 1929*bb4ee6a4SAndroid Build Coastguard Worker let mut cpuid = whpx.get_supported_cpuid()?; 1930*bb4ee6a4SAndroid Build Coastguard Worker 1931*bb4ee6a4SAndroid Build Coastguard Worker // Adjust them for crosvm 1932*bb4ee6a4SAndroid Build Coastguard Worker for entry in cpuid.cpu_id_entries.iter_mut() { 1933*bb4ee6a4SAndroid Build Coastguard Worker adjust_cpuid(entry, &ctx); 1934*bb4ee6a4SAndroid Build Coastguard Worker } 1935*bb4ee6a4SAndroid Build Coastguard Worker 1936*bb4ee6a4SAndroid Build Coastguard Worker let vm = WhpxVm::new( 1937*bb4ee6a4SAndroid Build Coastguard Worker &whpx, 1938*bb4ee6a4SAndroid Build Coastguard Worker cpu_count, 1939*bb4ee6a4SAndroid Build Coastguard Worker mem, 1940*bb4ee6a4SAndroid Build Coastguard Worker cpuid, 1941*bb4ee6a4SAndroid Build Coastguard Worker apic_emulation, 1942*bb4ee6a4SAndroid Build Coastguard Worker Some(vm_evt_wrtube), 1943*bb4ee6a4SAndroid Build Coastguard Worker ) 1944*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::WhpxSetupError, "failed to create WHPX vm")?; 1945*bb4ee6a4SAndroid Build Coastguard Worker 1946*bb4ee6a4SAndroid Build Coastguard Worker Ok(vm) 1947*bb4ee6a4SAndroid Build Coastguard Worker } 1948*bb4ee6a4SAndroid Build Coastguard Worker 1949*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 1950*bb4ee6a4SAndroid Build Coastguard Worker fn create_gvm_irq_chip(vm: &GvmVm, vcpu_count: usize) -> base::Result<GvmIrqChip> { 1951*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating GVM irqchip"); 1952*bb4ee6a4SAndroid Build Coastguard Worker let irq_chip = GvmIrqChip::new(vm.try_clone()?, vcpu_count)?; 1953*bb4ee6a4SAndroid Build Coastguard Worker Ok(irq_chip) 1954*bb4ee6a4SAndroid Build Coastguard Worker } 1955*bb4ee6a4SAndroid Build Coastguard Worker 1956*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 1957*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 1958*bb4ee6a4SAndroid Build Coastguard Worker fn create_whpx_split_irq_chip( 1959*bb4ee6a4SAndroid Build Coastguard Worker vm: &WhpxVm, 1960*bb4ee6a4SAndroid Build Coastguard Worker ioapic_device_tube: Tube, 1961*bb4ee6a4SAndroid Build Coastguard Worker ) -> base::Result<WhpxSplitIrqChip> { 1962*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating WHPX split irqchip"); 1963*bb4ee6a4SAndroid Build Coastguard Worker WhpxSplitIrqChip::new( 1964*bb4ee6a4SAndroid Build Coastguard Worker vm.try_clone()?, 1965*bb4ee6a4SAndroid Build Coastguard Worker ioapic_device_tube, 1966*bb4ee6a4SAndroid Build Coastguard Worker None, // ioapic_pins 1967*bb4ee6a4SAndroid Build Coastguard Worker ) 1968*bb4ee6a4SAndroid Build Coastguard Worker } 1969*bb4ee6a4SAndroid Build Coastguard Worker 1970*bb4ee6a4SAndroid Build Coastguard Worker fn create_userspace_irq_chip<Vcpu>( 1971*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count: usize, 1972*bb4ee6a4SAndroid Build Coastguard Worker ioapic_device_tube: Tube, 1973*bb4ee6a4SAndroid Build Coastguard Worker ) -> base::Result<UserspaceIrqChip<Vcpu>> 1974*bb4ee6a4SAndroid Build Coastguard Worker where 1975*bb4ee6a4SAndroid Build Coastguard Worker Vcpu: VcpuArch + 'static, 1976*bb4ee6a4SAndroid Build Coastguard Worker { 1977*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating userspace irqchip"); 1978*bb4ee6a4SAndroid Build Coastguard Worker let irq_chip = 1979*bb4ee6a4SAndroid Build Coastguard Worker UserspaceIrqChip::new(vcpu_count, ioapic_device_tube, /* ioapic_pins: */ None)?; 1980*bb4ee6a4SAndroid Build Coastguard Worker Ok(irq_chip) 1981*bb4ee6a4SAndroid Build Coastguard Worker } 1982*bb4ee6a4SAndroid Build Coastguard Worker 1983*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_default_hypervisor() -> Option<HypervisorKind> { 1984*bb4ee6a4SAndroid Build Coastguard Worker // The ordering here matters from most preferable to the least. 1985*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 1986*bb4ee6a4SAndroid Build Coastguard Worker match hypervisor::whpx::Whpx::is_enabled() { 1987*bb4ee6a4SAndroid Build Coastguard Worker true => return Some(HypervisorKind::Whpx), 1988*bb4ee6a4SAndroid Build Coastguard Worker false => warn!("Whpx not enabled."), 1989*bb4ee6a4SAndroid Build Coastguard Worker }; 1990*bb4ee6a4SAndroid Build Coastguard Worker 1991*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 1992*bb4ee6a4SAndroid Build Coastguard Worker match Haxm::new() { 1993*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => return Some(HypervisorKind::Ghaxm), 1994*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => warn!("Cannot initialize HAXM: {}", e), 1995*bb4ee6a4SAndroid Build Coastguard Worker }; 1996*bb4ee6a4SAndroid Build Coastguard Worker 1997*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 1998*bb4ee6a4SAndroid Build Coastguard Worker // Make sure Gvm device can be opened before selecting it. 1999*bb4ee6a4SAndroid Build Coastguard Worker match Gvm::new() { 2000*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => return Some(HypervisorKind::Gvm), 2001*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => warn!("Cannot initialize GVM: {}", e), 2002*bb4ee6a4SAndroid Build Coastguard Worker }; 2003*bb4ee6a4SAndroid Build Coastguard Worker 2004*bb4ee6a4SAndroid Build Coastguard Worker None 2005*bb4ee6a4SAndroid Build Coastguard Worker } 2006*bb4ee6a4SAndroid Build Coastguard Worker 2007*bb4ee6a4SAndroid Build Coastguard Worker fn setup_vm_components(cfg: &Config) -> Result<VmComponents> { 2008*bb4ee6a4SAndroid Build Coastguard Worker let initrd_image = if let Some(initrd_path) = &cfg.initrd_path { 2009*bb4ee6a4SAndroid Build Coastguard Worker Some( 2010*bb4ee6a4SAndroid Build Coastguard Worker File::open(initrd_path).with_exit_context(Exit::OpenInitrd, || { 2011*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open initrd {}", initrd_path.display()) 2012*bb4ee6a4SAndroid Build Coastguard Worker })?, 2013*bb4ee6a4SAndroid Build Coastguard Worker ) 2014*bb4ee6a4SAndroid Build Coastguard Worker } else { 2015*bb4ee6a4SAndroid Build Coastguard Worker None 2016*bb4ee6a4SAndroid Build Coastguard Worker }; 2017*bb4ee6a4SAndroid Build Coastguard Worker 2018*bb4ee6a4SAndroid Build Coastguard Worker let vm_image = match cfg.executable_path { 2019*bb4ee6a4SAndroid Build Coastguard Worker Some(Executable::Kernel(ref kernel_path)) => VmImage::Kernel( 2020*bb4ee6a4SAndroid Build Coastguard Worker File::open(kernel_path).with_exit_context(Exit::OpenKernel, || { 2021*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open kernel image {}", kernel_path.display(),) 2022*bb4ee6a4SAndroid Build Coastguard Worker })?, 2023*bb4ee6a4SAndroid Build Coastguard Worker ), 2024*bb4ee6a4SAndroid Build Coastguard Worker Some(Executable::Bios(ref bios_path)) => { 2025*bb4ee6a4SAndroid Build Coastguard Worker VmImage::Bios(File::open(bios_path).with_exit_context(Exit::OpenBios, || { 2026*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open bios {}", bios_path.display()) 2027*bb4ee6a4SAndroid Build Coastguard Worker })?) 2028*bb4ee6a4SAndroid Build Coastguard Worker } 2029*bb4ee6a4SAndroid Build Coastguard Worker _ => panic!("Did not receive a bios or kernel, should be impossible."), 2030*bb4ee6a4SAndroid Build Coastguard Worker }; 2031*bb4ee6a4SAndroid Build Coastguard Worker 2032*bb4ee6a4SAndroid Build Coastguard Worker let swiotlb = if let Some(size) = cfg.swiotlb { 2033*bb4ee6a4SAndroid Build Coastguard Worker Some( 2034*bb4ee6a4SAndroid Build Coastguard Worker size.checked_mul(1024 * 1024) 2035*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| anyhow!("requested swiotlb size too large"))?, 2036*bb4ee6a4SAndroid Build Coastguard Worker ) 2037*bb4ee6a4SAndroid Build Coastguard Worker } else if matches!(cfg.protection_type, ProtectionType::Unprotected) { 2038*bb4ee6a4SAndroid Build Coastguard Worker None 2039*bb4ee6a4SAndroid Build Coastguard Worker } else { 2040*bb4ee6a4SAndroid Build Coastguard Worker Some(64 * 1024 * 1024) 2041*bb4ee6a4SAndroid Build Coastguard Worker }; 2042*bb4ee6a4SAndroid Build Coastguard Worker 2043*bb4ee6a4SAndroid Build Coastguard Worker let (pflash_image, pflash_block_size) = if let Some(pflash_parameters) = &cfg.pflash_parameters 2044*bb4ee6a4SAndroid Build Coastguard Worker { 2045*bb4ee6a4SAndroid Build Coastguard Worker ( 2046*bb4ee6a4SAndroid Build Coastguard Worker Some( 2047*bb4ee6a4SAndroid Build Coastguard Worker open_file_or_duplicate( 2048*bb4ee6a4SAndroid Build Coastguard Worker &pflash_parameters.path, 2049*bb4ee6a4SAndroid Build Coastguard Worker OpenOptions::new().read(true).write(true), 2050*bb4ee6a4SAndroid Build Coastguard Worker ) 2051*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| { 2052*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open pflash {}", pflash_parameters.path.display()) 2053*bb4ee6a4SAndroid Build Coastguard Worker })?, 2054*bb4ee6a4SAndroid Build Coastguard Worker ), 2055*bb4ee6a4SAndroid Build Coastguard Worker pflash_parameters.block_size, 2056*bb4ee6a4SAndroid Build Coastguard Worker ) 2057*bb4ee6a4SAndroid Build Coastguard Worker } else { 2058*bb4ee6a4SAndroid Build Coastguard Worker (None, 0) 2059*bb4ee6a4SAndroid Build Coastguard Worker }; 2060*bb4ee6a4SAndroid Build Coastguard Worker 2061*bb4ee6a4SAndroid Build Coastguard Worker Ok(VmComponents { 2062*bb4ee6a4SAndroid Build Coastguard Worker memory_size: cfg 2063*bb4ee6a4SAndroid Build Coastguard Worker .memory 2064*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(256) 2065*bb4ee6a4SAndroid Build Coastguard Worker .checked_mul(1024 * 1024) 2066*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| anyhow!("requested memory size too large"))?, 2067*bb4ee6a4SAndroid Build Coastguard Worker swiotlb, 2068*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count: cfg.vcpu_count.unwrap_or(1), 2069*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg_enable: false, 2070*bb4ee6a4SAndroid Build Coastguard Worker bootorder_fw_cfg_blob: Vec::new(), 2071*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity: cfg.vcpu_affinity.clone(), 2072*bb4ee6a4SAndroid Build Coastguard Worker cpu_clusters: cfg.cpu_clusters.clone(), 2073*bb4ee6a4SAndroid Build Coastguard Worker cpu_capacity: cfg.cpu_capacity.clone(), 2074*bb4ee6a4SAndroid Build Coastguard Worker no_smt: cfg.no_smt, 2075*bb4ee6a4SAndroid Build Coastguard Worker hugepages: cfg.hugepages, 2076*bb4ee6a4SAndroid Build Coastguard Worker hv_cfg: hypervisor::Config { 2077*bb4ee6a4SAndroid Build Coastguard Worker protection_type: cfg.protection_type, 2078*bb4ee6a4SAndroid Build Coastguard Worker }, 2079*bb4ee6a4SAndroid Build Coastguard Worker vm_image, 2080*bb4ee6a4SAndroid Build Coastguard Worker android_fstab: cfg 2081*bb4ee6a4SAndroid Build Coastguard Worker .android_fstab 2082*bb4ee6a4SAndroid Build Coastguard Worker .as_ref() 2083*bb4ee6a4SAndroid Build Coastguard Worker .map(|x| { 2084*bb4ee6a4SAndroid Build Coastguard Worker File::open(x).with_exit_context(Exit::OpenAndroidFstab, || { 2085*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open android fstab file {}", x.display()) 2086*bb4ee6a4SAndroid Build Coastguard Worker }) 2087*bb4ee6a4SAndroid Build Coastguard Worker }) 2088*bb4ee6a4SAndroid Build Coastguard Worker .map_or(Ok(None), |v| v.map(Some))?, 2089*bb4ee6a4SAndroid Build Coastguard Worker pstore: cfg.pstore.clone(), 2090*bb4ee6a4SAndroid Build Coastguard Worker pflash_block_size, 2091*bb4ee6a4SAndroid Build Coastguard Worker pflash_image, 2092*bb4ee6a4SAndroid Build Coastguard Worker initrd_image, 2093*bb4ee6a4SAndroid Build Coastguard Worker extra_kernel_params: cfg.params.clone(), 2094*bb4ee6a4SAndroid Build Coastguard Worker acpi_sdts: cfg 2095*bb4ee6a4SAndroid Build Coastguard Worker .acpi_tables 2096*bb4ee6a4SAndroid Build Coastguard Worker .iter() 2097*bb4ee6a4SAndroid Build Coastguard Worker .map(|path| { 2098*bb4ee6a4SAndroid Build Coastguard Worker SDT::from_file(path).with_exit_context(Exit::OpenAcpiTable, || { 2099*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open ACPI file {}", path.display()) 2100*bb4ee6a4SAndroid Build Coastguard Worker }) 2101*bb4ee6a4SAndroid Build Coastguard Worker }) 2102*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Result<Vec<SDT>>>()?, 2103*bb4ee6a4SAndroid Build Coastguard Worker rt_cpus: cfg.rt_cpus.clone(), 2104*bb4ee6a4SAndroid Build Coastguard Worker delay_rt: cfg.delay_rt, 2105*bb4ee6a4SAndroid Build Coastguard Worker no_i8042: cfg.no_i8042, 2106*bb4ee6a4SAndroid Build Coastguard Worker no_rtc: cfg.no_rtc, 2107*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology: cfg.host_cpu_topology, 2108*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 2109*bb4ee6a4SAndroid Build Coastguard Worker force_s2idle: cfg.force_s2idle, 2110*bb4ee6a4SAndroid Build Coastguard Worker fw_cfg_parameters: cfg.fw_cfg_parameters.clone(), 2111*bb4ee6a4SAndroid Build Coastguard Worker itmt: false, 2112*bb4ee6a4SAndroid Build Coastguard Worker pvm_fw: None, 2113*bb4ee6a4SAndroid Build Coastguard Worker pci_config: cfg.pci_config, 2114*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 2115*bb4ee6a4SAndroid Build Coastguard Worker smbios: cfg.smbios.clone(), 2116*bb4ee6a4SAndroid Build Coastguard Worker dynamic_power_coefficient: cfg.dynamic_power_coefficient.clone(), 2117*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 2118*bb4ee6a4SAndroid Build Coastguard Worker break_linux_pci_config_io: cfg.break_linux_pci_config_io, 2119*bb4ee6a4SAndroid Build Coastguard Worker boot_cpu: cfg.boot_cpu, 2120*bb4ee6a4SAndroid Build Coastguard Worker }) 2121*bb4ee6a4SAndroid Build Coastguard Worker } 2122*bb4ee6a4SAndroid Build Coastguard Worker 2123*bb4ee6a4SAndroid Build Coastguard Worker // Enum that allows us to assign a variable to what is essentially a &dyn IrqChipArch. 2124*bb4ee6a4SAndroid Build Coastguard Worker enum WindowsIrqChip<V: VcpuArch> { 2125*bb4ee6a4SAndroid Build Coastguard Worker Userspace(UserspaceIrqChip<V>), 2126*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 2127*bb4ee6a4SAndroid Build Coastguard Worker Gvm(GvmIrqChip), 2128*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 2129*bb4ee6a4SAndroid Build Coastguard Worker WhpxSplit(WhpxSplitIrqChip), 2130*bb4ee6a4SAndroid Build Coastguard Worker } 2131*bb4ee6a4SAndroid Build Coastguard Worker 2132*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuArch> WindowsIrqChip<V> { 2133*bb4ee6a4SAndroid Build Coastguard Worker // Convert our enum to a &mut dyn IrqChipArch 2134*bb4ee6a4SAndroid Build Coastguard Worker fn as_mut(&mut self) -> &mut dyn IrqChipArch { 2135*bb4ee6a4SAndroid Build Coastguard Worker match self { 2136*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Userspace(i) => i, 2137*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 2138*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Gvm(i) => i, 2139*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 2140*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::WhpxSplit(i) => i, 2141*bb4ee6a4SAndroid Build Coastguard Worker } 2142*bb4ee6a4SAndroid Build Coastguard Worker } 2143*bb4ee6a4SAndroid Build Coastguard Worker } 2144*bb4ee6a4SAndroid Build Coastguard Worker 2145*bb4ee6a4SAndroid Build Coastguard Worker /// Storage for the VM TSC offset for each vcpu. Stored in a static because the tracing thread will 2146*bb4ee6a4SAndroid Build Coastguard Worker /// need access to it when tracing is enabled. 2147*bb4ee6a4SAndroid Build Coastguard Worker static TSC_OFFSETS: sync::Mutex<Vec<Option<u64>>> = sync::Mutex::new(Vec::new()); 2148*bb4ee6a4SAndroid Build Coastguard Worker 2149*bb4ee6a4SAndroid Build Coastguard Worker /// Save the TSC offset for a particular vcpu. 2150*bb4ee6a4SAndroid Build Coastguard Worker /// 2151*bb4ee6a4SAndroid Build Coastguard Worker /// After setting the TSC offset for a vcpu, this function checks the standard deviation of offsets 2152*bb4ee6a4SAndroid Build Coastguard Worker /// for all the VCPUs and logs this information. If the TSC offsets differ too much between vcpus 2153*bb4ee6a4SAndroid Build Coastguard Worker /// it can cause clock issues in the guest. 2154*bb4ee6a4SAndroid Build Coastguard Worker pub fn save_vcpu_tsc_offset(offset: u64, vcpu_id: usize) { 2155*bb4ee6a4SAndroid Build Coastguard Worker let offsets_copy = { 2156*bb4ee6a4SAndroid Build Coastguard Worker let mut offsets = TSC_OFFSETS.lock(); 2157*bb4ee6a4SAndroid Build Coastguard Worker // make sure offsets vec is large enough before inserting 2158*bb4ee6a4SAndroid Build Coastguard Worker let newlen = std::cmp::max(offsets.len(), vcpu_id + 1); 2159*bb4ee6a4SAndroid Build Coastguard Worker offsets.resize(newlen, None); 2160*bb4ee6a4SAndroid Build Coastguard Worker offsets[vcpu_id] = Some(offset); 2161*bb4ee6a4SAndroid Build Coastguard Worker 2162*bb4ee6a4SAndroid Build Coastguard Worker offsets.clone() 2163*bb4ee6a4SAndroid Build Coastguard Worker }; 2164*bb4ee6a4SAndroid Build Coastguard Worker 2165*bb4ee6a4SAndroid Build Coastguard Worker // do statistics on a clone of the offsets so we don't hold up other vcpus at this point 2166*bb4ee6a4SAndroid Build Coastguard Worker info!( 2167*bb4ee6a4SAndroid Build Coastguard Worker "TSC offset standard deviation is: {}", 2168*bb4ee6a4SAndroid Build Coastguard Worker standard_deviation( 2169*bb4ee6a4SAndroid Build Coastguard Worker &offsets_copy 2170*bb4ee6a4SAndroid Build Coastguard Worker .iter() 2171*bb4ee6a4SAndroid Build Coastguard Worker .filter(|x| x.is_some()) 2172*bb4ee6a4SAndroid Build Coastguard Worker .map(|x| x.unwrap() as u128) 2173*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Vec<u128>>() 2174*bb4ee6a4SAndroid Build Coastguard Worker ) 2175*bb4ee6a4SAndroid Build Coastguard Worker ); 2176*bb4ee6a4SAndroid Build Coastguard Worker } 2177*bb4ee6a4SAndroid Build Coastguard Worker 2178*bb4ee6a4SAndroid Build Coastguard Worker /// Get the TSC offset of any vcpu. It will pick the first non-None offset it finds in TSC_OFFSETS. 2179*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "perfetto")] 2180*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_vcpu_tsc_offset() -> u64 { 2181*bb4ee6a4SAndroid Build Coastguard Worker if let Some(offset) = TSC_OFFSETS.lock().iter().flatten().next() { 2182*bb4ee6a4SAndroid Build Coastguard Worker return *offset; 2183*bb4ee6a4SAndroid Build Coastguard Worker } 2184*bb4ee6a4SAndroid Build Coastguard Worker 0 2185*bb4ee6a4SAndroid Build Coastguard Worker } 2186*bb4ee6a4SAndroid Build Coastguard Worker 2187*bb4ee6a4SAndroid Build Coastguard Worker /// Callback that is registered with tracing crate, and will be called by the tracing thread when 2188*bb4ee6a4SAndroid Build Coastguard Worker /// tracing is enabled or disabled. Regardless of whether tracing is being enabled or disabled for 2189*bb4ee6a4SAndroid Build Coastguard Worker /// a given category or instance, we just emit a clock snapshot that maps the guest TSC to the 2190*bb4ee6a4SAndroid Build Coastguard Worker /// host TSC. Redundant snapshots should not be a problem for perfetto. 2191*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "perfetto")] 2192*bb4ee6a4SAndroid Build Coastguard Worker fn set_tsc_clock_snapshot() { 2193*bb4ee6a4SAndroid Build Coastguard Worker let freq = match devices::tsc::tsc_frequency() { 2194*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 2195*bb4ee6a4SAndroid Build Coastguard Worker error!( 2196*bb4ee6a4SAndroid Build Coastguard Worker "Could not determine tsc frequency, unable to snapshot tsc offset: {}", 2197*bb4ee6a4SAndroid Build Coastguard Worker e 2198*bb4ee6a4SAndroid Build Coastguard Worker ); 2199*bb4ee6a4SAndroid Build Coastguard Worker return; 2200*bb4ee6a4SAndroid Build Coastguard Worker } 2201*bb4ee6a4SAndroid Build Coastguard Worker Ok(freq) => freq, 2202*bb4ee6a4SAndroid Build Coastguard Worker }; 2203*bb4ee6a4SAndroid Build Coastguard Worker 2204*bb4ee6a4SAndroid Build Coastguard Worker // The offset is host-guest tsc value 2205*bb4ee6a4SAndroid Build Coastguard Worker let offset = get_vcpu_tsc_offset(); 2206*bb4ee6a4SAndroid Build Coastguard Worker // Safe because _rdtsc takes no arguments; 2207*bb4ee6a4SAndroid Build Coastguard Worker let host_tsc = unsafe { std::arch::x86_64::_rdtsc() }; 2208*bb4ee6a4SAndroid Build Coastguard Worker perfetto::snapshot_clock(perfetto::ClockSnapshot::new( 2209*bb4ee6a4SAndroid Build Coastguard Worker // Technically our multiplier should be freq/1_000_000_000, but perfetto doesn't 2210*bb4ee6a4SAndroid Build Coastguard Worker // support floating point multipliers yet. So for now we set the freq in Hz and rely 2211*bb4ee6a4SAndroid Build Coastguard Worker // on the merge tool to fix it. 2212*bb4ee6a4SAndroid Build Coastguard Worker perfetto::Clock::new( 2213*bb4ee6a4SAndroid Build Coastguard Worker perfetto::BuiltinClock::Tsc as u32, 2214*bb4ee6a4SAndroid Build Coastguard Worker host_tsc.wrapping_add(offset), 2215*bb4ee6a4SAndroid Build Coastguard Worker ) 2216*bb4ee6a4SAndroid Build Coastguard Worker .set_multiplier(freq as u64), 2217*bb4ee6a4SAndroid Build Coastguard Worker perfetto::Clock::new( 2218*bb4ee6a4SAndroid Build Coastguard Worker // The host builtin clock ids are all offset from the guest ids by 2219*bb4ee6a4SAndroid Build Coastguard Worker // HOST_GUEST_CLOCK_ID_OFFSET when the traces are merged. Because this snapshot 2220*bb4ee6a4SAndroid Build Coastguard Worker // contains both a guest and host clock, we need to offset it before merge. 2221*bb4ee6a4SAndroid Build Coastguard Worker perfetto::BuiltinClock::Tsc as u32 + cros_tracing::HOST_GUEST_CLOCK_ID_OFFSET, 2222*bb4ee6a4SAndroid Build Coastguard Worker host_tsc, 2223*bb4ee6a4SAndroid Build Coastguard Worker ) 2224*bb4ee6a4SAndroid Build Coastguard Worker .set_multiplier(freq as u64), 2225*bb4ee6a4SAndroid Build Coastguard Worker )); 2226*bb4ee6a4SAndroid Build Coastguard Worker } 2227*bb4ee6a4SAndroid Build Coastguard Worker 2228*bb4ee6a4SAndroid Build Coastguard Worker /// Launches run_config for the broker, reading configuration from a TubeTransporter. 2229*bb4ee6a4SAndroid Build Coastguard Worker pub fn run_config_for_broker(raw_tube_transporter: RawDescriptor) -> Result<ExitState> { 2230*bb4ee6a4SAndroid Build Coastguard Worker let tube_transporter = 2231*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 2232*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that raw_transport_tube is valid (passed by inheritance), and that 2233*bb4ee6a4SAndroid Build Coastguard Worker // the blocking & framing modes are accurate because we create them ourselves in the broker. 2234*bb4ee6a4SAndroid Build Coastguard Worker unsafe { TubeTransporterReader::from_raw_descriptor(raw_tube_transporter) }; 2235*bb4ee6a4SAndroid Build Coastguard Worker 2236*bb4ee6a4SAndroid Build Coastguard Worker let mut tube_data_list = tube_transporter 2237*bb4ee6a4SAndroid Build Coastguard Worker .read_tubes() 2238*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeTransporterInit, "failed to init tube transporter")?; 2239*bb4ee6a4SAndroid Build Coastguard Worker 2240*bb4ee6a4SAndroid Build Coastguard Worker let bootstrap_tube = tube_data_list 2241*bb4ee6a4SAndroid Build Coastguard Worker .get_tube(TubeToken::Bootstrap) 2242*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to get bootstrap tube")?; 2243*bb4ee6a4SAndroid Build Coastguard Worker 2244*bb4ee6a4SAndroid Build Coastguard Worker let mut cfg: Config = bootstrap_tube 2245*bb4ee6a4SAndroid Build Coastguard Worker .recv::<Config>() 2246*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to read bootstrap tube")?; 2247*bb4ee6a4SAndroid Build Coastguard Worker 2248*bb4ee6a4SAndroid Build Coastguard Worker let startup_args: CommonChildStartupArgs = bootstrap_tube 2249*bb4ee6a4SAndroid Build Coastguard Worker .recv::<CommonChildStartupArgs>() 2250*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to read bootstrap tube")?; 2251*bb4ee6a4SAndroid Build Coastguard Worker let _child_cleanup = common_child_setup(startup_args).exit_context( 2252*bb4ee6a4SAndroid Build Coastguard Worker Exit::CommonChildSetupError, 2253*bb4ee6a4SAndroid Build Coastguard Worker "failed to perform common child setup", 2254*bb4ee6a4SAndroid Build Coastguard Worker )?; 2255*bb4ee6a4SAndroid Build Coastguard Worker 2256*bb4ee6a4SAndroid Build Coastguard Worker cfg.broker_shutdown_event = Some( 2257*bb4ee6a4SAndroid Build Coastguard Worker bootstrap_tube 2258*bb4ee6a4SAndroid Build Coastguard Worker .recv::<Event>() 2259*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to read bootstrap tube")?, 2260*bb4ee6a4SAndroid Build Coastguard Worker ); 2261*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "crash-report")] 2262*bb4ee6a4SAndroid Build Coastguard Worker let crash_tube_map = bootstrap_tube 2263*bb4ee6a4SAndroid Build Coastguard Worker .recv::<HashMap<ProcessType, Vec<SendTube>>>() 2264*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to read bootstrap tube")?; 2265*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "crash-report")] 2266*bb4ee6a4SAndroid Build Coastguard Worker crash_report::set_crash_tube_map(crash_tube_map); 2267*bb4ee6a4SAndroid Build Coastguard Worker 2268*bb4ee6a4SAndroid Build Coastguard Worker let BrokerTubes { 2269*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube, 2270*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube, 2271*bb4ee6a4SAndroid Build Coastguard Worker } = bootstrap_tube 2272*bb4ee6a4SAndroid Build Coastguard Worker .recv::<BrokerTubes>() 2273*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::TubeFailure, "failed to read bootstrap tube")?; 2274*bb4ee6a4SAndroid Build Coastguard Worker 2275*bb4ee6a4SAndroid Build Coastguard Worker run_config_inner(cfg, vm_evt_wrtube, vm_evt_rdtube) 2276*bb4ee6a4SAndroid Build Coastguard Worker } 2277*bb4ee6a4SAndroid Build Coastguard Worker 2278*bb4ee6a4SAndroid Build Coastguard Worker pub fn run_config(cfg: Config) -> Result<ExitState> { 2279*bb4ee6a4SAndroid Build Coastguard Worker let _raise_timer_resolution = enable_high_res_timers() 2280*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::EnableHighResTimer, "failed to enable high res timer")?; 2281*bb4ee6a4SAndroid Build Coastguard Worker 2282*bb4ee6a4SAndroid Build Coastguard Worker // There is no broker when using run_config(), so the vm_evt tubes need to be created. 2283*bb4ee6a4SAndroid Build Coastguard Worker let (vm_evt_wrtube, vm_evt_rdtube) = 2284*bb4ee6a4SAndroid Build Coastguard Worker Tube::directional_pair().context("failed to create vm event tube")?; 2285*bb4ee6a4SAndroid Build Coastguard Worker 2286*bb4ee6a4SAndroid Build Coastguard Worker run_config_inner(cfg, vm_evt_wrtube, vm_evt_rdtube) 2287*bb4ee6a4SAndroid Build Coastguard Worker } 2288*bb4ee6a4SAndroid Build Coastguard Worker 2289*bb4ee6a4SAndroid Build Coastguard Worker fn create_guest_memory( 2290*bb4ee6a4SAndroid Build Coastguard Worker components: &VmComponents, 2291*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout: &<Arch as LinuxArch>::ArchMemoryLayout, 2292*bb4ee6a4SAndroid Build Coastguard Worker hypervisor: &impl Hypervisor, 2293*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<GuestMemory> { 2294*bb4ee6a4SAndroid Build Coastguard Worker let guest_mem_layout = Arch::guest_memory_layout(components, arch_memory_layout, hypervisor) 2295*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 2296*bb4ee6a4SAndroid Build Coastguard Worker Exit::GuestMemoryLayout, 2297*bb4ee6a4SAndroid Build Coastguard Worker "failed to create guest memory layout", 2298*bb4ee6a4SAndroid Build Coastguard Worker )?; 2299*bb4ee6a4SAndroid Build Coastguard Worker GuestMemory::new_with_options(&guest_mem_layout) 2300*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CreateGuestMemory, "failed to create guest memory") 2301*bb4ee6a4SAndroid Build Coastguard Worker } 2302*bb4ee6a4SAndroid Build Coastguard Worker 2303*bb4ee6a4SAndroid Build Coastguard Worker fn run_config_inner( 2304*bb4ee6a4SAndroid Build Coastguard Worker cfg: Config, 2305*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: SendTube, 2306*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube: RecvTube, 2307*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ExitState> { 2308*bb4ee6a4SAndroid Build Coastguard Worker product::setup_common_metric_invariants(&cfg); 2309*bb4ee6a4SAndroid Build Coastguard Worker 2310*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "perfetto")] 2311*bb4ee6a4SAndroid Build Coastguard Worker cros_tracing::add_per_trace_callback(set_tsc_clock_snapshot); 2312*bb4ee6a4SAndroid Build Coastguard Worker 2313*bb4ee6a4SAndroid Build Coastguard Worker let components: VmComponents = setup_vm_components(&cfg)?; 2314*bb4ee6a4SAndroid Build Coastguard Worker let arch_memory_layout = Arch::arch_memory_layout(&components)?; 2315*bb4ee6a4SAndroid Build Coastguard Worker 2316*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_mut)] 2317*bb4ee6a4SAndroid Build Coastguard Worker let mut hypervisor = cfg 2318*bb4ee6a4SAndroid Build Coastguard Worker .hypervisor 2319*bb4ee6a4SAndroid Build Coastguard Worker .or_else(get_default_hypervisor) 2320*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::NoDefaultHypervisor, "no enabled hypervisor")?; 2321*bb4ee6a4SAndroid Build Coastguard Worker 2322*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 2323*bb4ee6a4SAndroid Build Coastguard Worker if hypervisor::whpx::Whpx::is_enabled() { 2324*bb4ee6a4SAndroid Build Coastguard Worker // If WHPX is enabled, no other hypervisor can be used, so just override it 2325*bb4ee6a4SAndroid Build Coastguard Worker hypervisor = HypervisorKind::Whpx; 2326*bb4ee6a4SAndroid Build Coastguard Worker } 2327*bb4ee6a4SAndroid Build Coastguard Worker 2328*bb4ee6a4SAndroid Build Coastguard Worker match hypervisor { 2329*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "haxm")] 2330*bb4ee6a4SAndroid Build Coastguard Worker HypervisorKind::Haxm | HypervisorKind::Ghaxm => { 2331*bb4ee6a4SAndroid Build Coastguard Worker if hypervisor == HypervisorKind::Haxm { 2332*bb4ee6a4SAndroid Build Coastguard Worker set_use_ghaxm(false); 2333*bb4ee6a4SAndroid Build Coastguard Worker } 2334*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating HAXM ghaxm={}", get_use_ghaxm()); 2335*bb4ee6a4SAndroid Build Coastguard Worker let haxm = Haxm::new()?; 2336*bb4ee6a4SAndroid Build Coastguard Worker let guest_mem = create_guest_memory(&components, &arch_memory_layout, &haxm)?; 2337*bb4ee6a4SAndroid Build Coastguard Worker let vm = create_haxm_vm(haxm, guest_mem, &cfg.kernel_log_file)?; 2338*bb4ee6a4SAndroid Build Coastguard Worker let (ioapic_host_tube, ioapic_device_tube) = 2339*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2340*bb4ee6a4SAndroid Build Coastguard Worker let irq_chip = 2341*bb4ee6a4SAndroid Build Coastguard Worker create_userspace_irq_chip::<HaxmVcpu>(components.vcpu_count, ioapic_device_tube)?; 2342*bb4ee6a4SAndroid Build Coastguard Worker run_vm::<HaxmVcpu, HaxmVm>( 2343*bb4ee6a4SAndroid Build Coastguard Worker cfg, 2344*bb4ee6a4SAndroid Build Coastguard Worker components, 2345*bb4ee6a4SAndroid Build Coastguard Worker &arch_memory_layout, 2346*bb4ee6a4SAndroid Build Coastguard Worker vm, 2347*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Userspace(irq_chip).as_mut(), 2348*bb4ee6a4SAndroid Build Coastguard Worker Some(ioapic_host_tube), 2349*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube, 2350*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube, 2351*bb4ee6a4SAndroid Build Coastguard Worker ) 2352*bb4ee6a4SAndroid Build Coastguard Worker } 2353*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")] 2354*bb4ee6a4SAndroid Build Coastguard Worker HypervisorKind::Whpx => { 2355*bb4ee6a4SAndroid Build Coastguard Worker let apic_emulation_supported = 2356*bb4ee6a4SAndroid Build Coastguard Worker Whpx::check_whpx_feature(WhpxFeature::LocalApicEmulation) 2357*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::WhpxSetupError, "failed to set up whpx")?; 2358*bb4ee6a4SAndroid Build Coastguard Worker 2359*bb4ee6a4SAndroid Build Coastguard Worker let no_smt = cfg.no_smt; 2360*bb4ee6a4SAndroid Build Coastguard Worker 2361*bb4ee6a4SAndroid Build Coastguard Worker // Default to WhpxSplitIrqChip if it's supported because it's more performant 2362*bb4ee6a4SAndroid Build Coastguard Worker let irq_chip = cfg.irq_chip.unwrap_or(if apic_emulation_supported { 2363*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Split 2364*bb4ee6a4SAndroid Build Coastguard Worker } else { 2365*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Userspace 2366*bb4ee6a4SAndroid Build Coastguard Worker }); 2367*bb4ee6a4SAndroid Build Coastguard Worker 2368*bb4ee6a4SAndroid Build Coastguard Worker // Both WHPX irq chips use a userspace IOAPIC 2369*bb4ee6a4SAndroid Build Coastguard Worker let (ioapic_host_tube, ioapic_device_tube) = 2370*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2371*bb4ee6a4SAndroid Build Coastguard Worker 2372*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating Whpx"); 2373*bb4ee6a4SAndroid Build Coastguard Worker let whpx = Whpx::new()?; 2374*bb4ee6a4SAndroid Build Coastguard Worker let guest_mem = create_guest_memory(&components, &arch_memory_layout, &whpx)?; 2375*bb4ee6a4SAndroid Build Coastguard Worker let vm = create_whpx_vm( 2376*bb4ee6a4SAndroid Build Coastguard Worker whpx, 2377*bb4ee6a4SAndroid Build Coastguard Worker guest_mem, 2378*bb4ee6a4SAndroid Build Coastguard Worker components.vcpu_count, 2379*bb4ee6a4SAndroid Build Coastguard Worker no_smt, 2380*bb4ee6a4SAndroid Build Coastguard Worker apic_emulation_supported && irq_chip == IrqChipKind::Split, 2381*bb4ee6a4SAndroid Build Coastguard Worker cfg.force_calibrated_tsc_leaf, 2382*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube 2383*bb4ee6a4SAndroid Build Coastguard Worker .try_clone() 2384*bb4ee6a4SAndroid Build Coastguard Worker .expect("could not clone vm_evt_wrtube"), 2385*bb4ee6a4SAndroid Build Coastguard Worker )?; 2386*bb4ee6a4SAndroid Build Coastguard Worker 2387*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_chip = match irq_chip { 2388*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Kernel => unimplemented!("Kernel irqchip mode not supported by WHPX"), 2389*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Split => { 2390*bb4ee6a4SAndroid Build Coastguard Worker if !apic_emulation_supported { 2391*bb4ee6a4SAndroid Build Coastguard Worker panic!( 2392*bb4ee6a4SAndroid Build Coastguard Worker "split irqchip specified but your WHPX version does not support \ 2393*bb4ee6a4SAndroid Build Coastguard Worker local apic emulation" 2394*bb4ee6a4SAndroid Build Coastguard Worker ); 2395*bb4ee6a4SAndroid Build Coastguard Worker } 2396*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::WhpxSplit(create_whpx_split_irq_chip(&vm, ioapic_device_tube)?) 2397*bb4ee6a4SAndroid Build Coastguard Worker } 2398*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Userspace => { 2399*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Userspace(create_userspace_irq_chip::<WhpxVcpu>( 2400*bb4ee6a4SAndroid Build Coastguard Worker components.vcpu_count, 2401*bb4ee6a4SAndroid Build Coastguard Worker ioapic_device_tube, 2402*bb4ee6a4SAndroid Build Coastguard Worker )?) 2403*bb4ee6a4SAndroid Build Coastguard Worker } 2404*bb4ee6a4SAndroid Build Coastguard Worker }; 2405*bb4ee6a4SAndroid Build Coastguard Worker run_vm::<WhpxVcpu, WhpxVm>( 2406*bb4ee6a4SAndroid Build Coastguard Worker cfg, 2407*bb4ee6a4SAndroid Build Coastguard Worker components, 2408*bb4ee6a4SAndroid Build Coastguard Worker &arch_memory_layout, 2409*bb4ee6a4SAndroid Build Coastguard Worker vm, 2410*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.as_mut(), 2411*bb4ee6a4SAndroid Build Coastguard Worker Some(ioapic_host_tube), 2412*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube, 2413*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube, 2414*bb4ee6a4SAndroid Build Coastguard Worker ) 2415*bb4ee6a4SAndroid Build Coastguard Worker } 2416*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gvm")] 2417*bb4ee6a4SAndroid Build Coastguard Worker HypervisorKind::Gvm => { 2418*bb4ee6a4SAndroid Build Coastguard Worker info!("Creating GVM"); 2419*bb4ee6a4SAndroid Build Coastguard Worker let gvm = Gvm::new()?; 2420*bb4ee6a4SAndroid Build Coastguard Worker let guest_mem = create_guest_memory(&components, &arch_memory_layout, &gvm)?; 2421*bb4ee6a4SAndroid Build Coastguard Worker let vm = create_gvm_vm(gvm, guest_mem)?; 2422*bb4ee6a4SAndroid Build Coastguard Worker let ioapic_host_tube; 2423*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_chip = match cfg.irq_chip.unwrap_or(IrqChipKind::Kernel) { 2424*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Split => unimplemented!("Split irqchip mode not supported by GVM"), 2425*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Kernel => { 2426*bb4ee6a4SAndroid Build Coastguard Worker ioapic_host_tube = None; 2427*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Gvm(create_gvm_irq_chip(&vm, components.vcpu_count)?) 2428*bb4ee6a4SAndroid Build Coastguard Worker } 2429*bb4ee6a4SAndroid Build Coastguard Worker IrqChipKind::Userspace => { 2430*bb4ee6a4SAndroid Build Coastguard Worker let (host_tube, ioapic_device_tube) = 2431*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2432*bb4ee6a4SAndroid Build Coastguard Worker ioapic_host_tube = Some(host_tube); 2433*bb4ee6a4SAndroid Build Coastguard Worker WindowsIrqChip::Userspace(create_userspace_irq_chip::<GvmVcpu>( 2434*bb4ee6a4SAndroid Build Coastguard Worker components.vcpu_count, 2435*bb4ee6a4SAndroid Build Coastguard Worker ioapic_device_tube, 2436*bb4ee6a4SAndroid Build Coastguard Worker )?) 2437*bb4ee6a4SAndroid Build Coastguard Worker } 2438*bb4ee6a4SAndroid Build Coastguard Worker }; 2439*bb4ee6a4SAndroid Build Coastguard Worker run_vm::<GvmVcpu, GvmVm>( 2440*bb4ee6a4SAndroid Build Coastguard Worker cfg, 2441*bb4ee6a4SAndroid Build Coastguard Worker components, 2442*bb4ee6a4SAndroid Build Coastguard Worker &arch_memory_layout, 2443*bb4ee6a4SAndroid Build Coastguard Worker vm, 2444*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.as_mut(), 2445*bb4ee6a4SAndroid Build Coastguard Worker ioapic_host_tube, 2446*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube, 2447*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube, 2448*bb4ee6a4SAndroid Build Coastguard Worker ) 2449*bb4ee6a4SAndroid Build Coastguard Worker } 2450*bb4ee6a4SAndroid Build Coastguard Worker } 2451*bb4ee6a4SAndroid Build Coastguard Worker } 2452*bb4ee6a4SAndroid Build Coastguard Worker 2453*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(feature = "haxm", feature = "gvm", feature = "whpx"))] 2454*bb4ee6a4SAndroid Build Coastguard Worker fn run_vm<Vcpu, V>( 2455*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_mut)] mut cfg: Config, 2456*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_mut)] mut components: VmComponents, 2457*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout: &<Arch as LinuxArch>::ArchMemoryLayout, 2458*bb4ee6a4SAndroid Build Coastguard Worker mut vm: V, 2459*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChipArch, 2460*bb4ee6a4SAndroid Build Coastguard Worker ioapic_host_tube: Option<Tube>, 2461*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: SendTube, 2462*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube: RecvTube, 2463*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ExitState> 2464*bb4ee6a4SAndroid Build Coastguard Worker where 2465*bb4ee6a4SAndroid Build Coastguard Worker Vcpu: VcpuArch + 'static, 2466*bb4ee6a4SAndroid Build Coastguard Worker V: VmArch + 'static, 2467*bb4ee6a4SAndroid Build Coastguard Worker { 2468*bb4ee6a4SAndroid Build Coastguard Worker let vm_memory_size_mb = components.memory_size / (1024 * 1024); 2469*bb4ee6a4SAndroid Build Coastguard Worker let mut control_tubes = Vec::new(); 2470*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_control_tubes = Vec::new(); 2471*bb4ee6a4SAndroid Build Coastguard Worker let mut vm_memory_control_tubes = Vec::new(); 2472*bb4ee6a4SAndroid Build Coastguard Worker // Create one control tube per disk. 2473*bb4ee6a4SAndroid Build Coastguard Worker let mut disk_device_tubes = Vec::new(); 2474*bb4ee6a4SAndroid Build Coastguard Worker let mut disk_host_tubes = Vec::new(); 2475*bb4ee6a4SAndroid Build Coastguard Worker let disk_count = cfg.disks.len(); 2476*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..disk_count { 2477*bb4ee6a4SAndroid Build Coastguard Worker let (disk_host_tube, disk_device_tube) = 2478*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2479*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes.push(disk_host_tube); 2480*bb4ee6a4SAndroid Build Coastguard Worker disk_device_tubes.push(disk_device_tube); 2481*bb4ee6a4SAndroid Build Coastguard Worker } 2482*bb4ee6a4SAndroid Build Coastguard Worker 2483*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ioapic_host_tube) = ioapic_host_tube { 2484*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes.push(ioapic_host_tube); 2485*bb4ee6a4SAndroid Build Coastguard Worker } 2486*bb4ee6a4SAndroid Build Coastguard Worker 2487*bb4ee6a4SAndroid Build Coastguard Worker // Balloon gets a special socket so balloon requests can be forwarded from the main process. 2488*bb4ee6a4SAndroid Build Coastguard Worker let (balloon_host_tube, balloon_device_tube) = if cfg.balloon { 2489*bb4ee6a4SAndroid Build Coastguard Worker let (balloon_host_tube, balloon_device_tube) = 2490*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2491*bb4ee6a4SAndroid Build Coastguard Worker (Some(balloon_host_tube), Some(balloon_device_tube)) 2492*bb4ee6a4SAndroid Build Coastguard Worker } else { 2493*bb4ee6a4SAndroid Build Coastguard Worker (None, None) 2494*bb4ee6a4SAndroid Build Coastguard Worker }; 2495*bb4ee6a4SAndroid Build Coastguard Worker // The balloon device also needs a tube to communicate back to the main process to 2496*bb4ee6a4SAndroid Build Coastguard Worker // handle remapping memory dynamically. 2497*bb4ee6a4SAndroid Build Coastguard Worker let dynamic_mapping_device_tube = if cfg.balloon { 2498*bb4ee6a4SAndroid Build Coastguard Worker let (dynamic_mapping_host_tube, dynamic_mapping_device_tube) = 2499*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2500*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes.push(dynamic_mapping_host_tube); 2501*bb4ee6a4SAndroid Build Coastguard Worker Some(dynamic_mapping_device_tube) 2502*bb4ee6a4SAndroid Build Coastguard Worker } else { 2503*bb4ee6a4SAndroid Build Coastguard Worker None 2504*bb4ee6a4SAndroid Build Coastguard Worker }; 2505*bb4ee6a4SAndroid Build Coastguard Worker 2506*bb4ee6a4SAndroid Build Coastguard Worker // PvClock gets a tube for handling suspend/resume requests from the main thread. 2507*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 2508*bb4ee6a4SAndroid Build Coastguard Worker let (pvclock_host_tube, pvclock_device_tube) = if cfg.pvclock { 2509*bb4ee6a4SAndroid Build Coastguard Worker let (host, device) = 2510*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().exit_context(Exit::CreateTube, "failed to create tube")?; 2511*bb4ee6a4SAndroid Build Coastguard Worker (Some(host), Some(device)) 2512*bb4ee6a4SAndroid Build Coastguard Worker } else { 2513*bb4ee6a4SAndroid Build Coastguard Worker (None, None) 2514*bb4ee6a4SAndroid Build Coastguard Worker }; 2515*bb4ee6a4SAndroid Build Coastguard Worker 2516*bb4ee6a4SAndroid Build Coastguard Worker let gralloc = RutabagaGralloc::new(RutabagaGrallocBackendFlags::new()) 2517*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CreateGralloc, "failed to create gralloc")?; 2518*bb4ee6a4SAndroid Build Coastguard Worker 2519*bb4ee6a4SAndroid Build Coastguard Worker let pstore_size = components.pstore.as_ref().map(|pstore| pstore.size as u64); 2520*bb4ee6a4SAndroid Build Coastguard Worker let mut sys_allocator = SystemAllocator::new( 2521*bb4ee6a4SAndroid Build Coastguard Worker Arch::get_system_allocator_config(&vm, arch_memory_layout), 2522*bb4ee6a4SAndroid Build Coastguard Worker pstore_size, 2523*bb4ee6a4SAndroid Build Coastguard Worker &cfg.mmio_address_ranges, 2524*bb4ee6a4SAndroid Build Coastguard Worker ) 2525*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to create system allocator")?; 2526*bb4ee6a4SAndroid Build Coastguard Worker 2527*bb4ee6a4SAndroid Build Coastguard Worker // Allocate the ramoops region first. 2528*bb4ee6a4SAndroid Build Coastguard Worker let ramoops_region = match &components.pstore { 2529*bb4ee6a4SAndroid Build Coastguard Worker Some(pstore) => Some( 2530*bb4ee6a4SAndroid Build Coastguard Worker arch::pstore::create_memory_region( 2531*bb4ee6a4SAndroid Build Coastguard Worker &mut vm, 2532*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator.reserved_region().unwrap(), 2533*bb4ee6a4SAndroid Build Coastguard Worker pstore, 2534*bb4ee6a4SAndroid Build Coastguard Worker ) 2535*bb4ee6a4SAndroid Build Coastguard Worker .exit_context( 2536*bb4ee6a4SAndroid Build Coastguard Worker Exit::Pstore, 2537*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to allocate pstore region {:?}", &components.pstore), 2538*bb4ee6a4SAndroid Build Coastguard Worker )?, 2539*bb4ee6a4SAndroid Build Coastguard Worker ), 2540*bb4ee6a4SAndroid Build Coastguard Worker None => None, 2541*bb4ee6a4SAndroid Build Coastguard Worker }; 2542*bb4ee6a4SAndroid Build Coastguard Worker 2543*bb4ee6a4SAndroid Build Coastguard Worker let init_balloon_size = components 2544*bb4ee6a4SAndroid Build Coastguard Worker .memory_size 2545*bb4ee6a4SAndroid Build Coastguard Worker .checked_sub(cfg.init_memory.map_or(components.memory_size, |m| { 2546*bb4ee6a4SAndroid Build Coastguard Worker m.checked_mul(1024 * 1024).unwrap_or(u64::MAX) 2547*bb4ee6a4SAndroid Build Coastguard Worker })) 2548*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to calculate init balloon size")?; 2549*bb4ee6a4SAndroid Build Coastguard Worker 2550*bb4ee6a4SAndroid Build Coastguard Worker let tsc_state = devices::tsc::tsc_state().exit_code(Exit::TscCalibrationFailed)?; 2551*bb4ee6a4SAndroid Build Coastguard Worker let tsc_sync_mitigations = get_tsc_sync_mitigations(&tsc_state, components.vcpu_count); 2552*bb4ee6a4SAndroid Build Coastguard Worker 2553*bb4ee6a4SAndroid Build Coastguard Worker if tsc_state.core_grouping.size() > 1 { 2554*bb4ee6a4SAndroid Build Coastguard Worker // Host TSCs are not in sync, log a metric about it. 2555*bb4ee6a4SAndroid Build Coastguard Worker warn!( 2556*bb4ee6a4SAndroid Build Coastguard Worker "Host TSCs are not in sync, applying the following mitigations: {:?}", 2557*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations 2558*bb4ee6a4SAndroid Build Coastguard Worker ); 2559*bb4ee6a4SAndroid Build Coastguard Worker log_descriptor( 2560*bb4ee6a4SAndroid Build Coastguard Worker MetricEventType::TscCoresOutOfSync, 2561*bb4ee6a4SAndroid Build Coastguard Worker // casting u64 as i64 is a no-op, so we don't lose any part of the bitmask 2562*bb4ee6a4SAndroid Build Coastguard Worker tsc_state.core_grouping.core_grouping_bitmask() as i64, 2563*bb4ee6a4SAndroid Build Coastguard Worker ); 2564*bb4ee6a4SAndroid Build Coastguard Worker } 2565*bb4ee6a4SAndroid Build Coastguard Worker 2566*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 2567*bb4ee6a4SAndroid Build Coastguard Worker let gpu_control_tube = cfg 2568*bb4ee6a4SAndroid Build Coastguard Worker .gpu_vmm_config 2569*bb4ee6a4SAndroid Build Coastguard Worker .as_mut() 2570*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|config| config.gpu_control_host_tube.take()); 2571*bb4ee6a4SAndroid Build Coastguard Worker let product_args = product::get_run_control_args(&mut cfg); 2572*bb4ee6a4SAndroid Build Coastguard Worker 2573*bb4ee6a4SAndroid Build Coastguard Worker // We open these files before lowering the token, as in the future a stricter policy may 2574*bb4ee6a4SAndroid Build Coastguard Worker // prevent it. 2575*bb4ee6a4SAndroid Build Coastguard Worker let dt_overlays = cfg 2576*bb4ee6a4SAndroid Build Coastguard Worker .device_tree_overlay 2577*bb4ee6a4SAndroid Build Coastguard Worker .iter() 2578*bb4ee6a4SAndroid Build Coastguard Worker .map(|o| { 2579*bb4ee6a4SAndroid Build Coastguard Worker Ok(DtbOverlay { 2580*bb4ee6a4SAndroid Build Coastguard Worker file: open_file_or_duplicate(o.path.as_path(), OpenOptions::new().read(true)) 2581*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| { 2582*bb4ee6a4SAndroid Build Coastguard Worker format!("failed to open device tree overlay {}", o.path.display()) 2583*bb4ee6a4SAndroid Build Coastguard Worker })?, 2584*bb4ee6a4SAndroid Build Coastguard Worker }) 2585*bb4ee6a4SAndroid Build Coastguard Worker }) 2586*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Result<Vec<DtbOverlay>>>()?; 2587*bb4ee6a4SAndroid Build Coastguard Worker 2588*bb4ee6a4SAndroid Build Coastguard Worker // Lower the token, locking the main process down to a stricter security policy. 2589*bb4ee6a4SAndroid Build Coastguard Worker // 2590*bb4ee6a4SAndroid Build Coastguard Worker // WARNING: 2591*bb4ee6a4SAndroid Build Coastguard Worker // 2592*bb4ee6a4SAndroid Build Coastguard Worker // Windows system calls can behave in unusual ways if they happen concurrently to the token 2593*bb4ee6a4SAndroid Build Coastguard Worker // lowering. For example, access denied can happen if Tube pairs are created in another thread 2594*bb4ee6a4SAndroid Build Coastguard Worker // (b/281108137), and lower_token happens right before the client pipe is connected. Tubes are 2595*bb4ee6a4SAndroid Build Coastguard Worker // not privileged resources, but can be broken due to the token changing unexpectedly. 2596*bb4ee6a4SAndroid Build Coastguard Worker // 2597*bb4ee6a4SAndroid Build Coastguard Worker // We explicitly lower the token here and *then* call run_control to make it clear that any 2598*bb4ee6a4SAndroid Build Coastguard Worker // resources that require a privileged token should be created on the main thread & passed into 2599*bb4ee6a4SAndroid Build Coastguard Worker // run_control, to follow the correct order: 2600*bb4ee6a4SAndroid Build Coastguard Worker // - Privileged resources are created. 2601*bb4ee6a4SAndroid Build Coastguard Worker // - Token is lowered. 2602*bb4ee6a4SAndroid Build Coastguard Worker // - Threads are spawned & may create more non-privileged resources (without fear of the token 2603*bb4ee6a4SAndroid Build Coastguard Worker // changing at an undefined time). 2604*bb4ee6a4SAndroid Build Coastguard Worker // 2605*bb4ee6a4SAndroid Build Coastguard Worker // Recommendation: If you find your code doesnt work in run_control because of the sandbox, you 2606*bb4ee6a4SAndroid Build Coastguard Worker // should split any resource creation to before this token lowering & pass the resources into 2607*bb4ee6a4SAndroid Build Coastguard Worker // run_control. Don't move the token lowering somewhere else without considering multi-threaded 2608*bb4ee6a4SAndroid Build Coastguard Worker // effects. 2609*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "sandbox")] 2610*bb4ee6a4SAndroid Build Coastguard Worker if sandbox::is_sandbox_target() { 2611*bb4ee6a4SAndroid Build Coastguard Worker sandbox::TargetServices::get() 2612*bb4ee6a4SAndroid Build Coastguard Worker .exit_code_from_err("failed to create sandbox")? 2613*bb4ee6a4SAndroid Build Coastguard Worker .expect("Could not create sandbox!") 2614*bb4ee6a4SAndroid Build Coastguard Worker .lower_token(); 2615*bb4ee6a4SAndroid Build Coastguard Worker } 2616*bb4ee6a4SAndroid Build Coastguard Worker 2617*bb4ee6a4SAndroid Build Coastguard Worker let virtio_snd_state_device_tube = create_snd_state_tube(&mut control_tubes)?; 2618*bb4ee6a4SAndroid Build Coastguard Worker 2619*bb4ee6a4SAndroid Build Coastguard Worker let (virtio_snd_host_mute_tube, virtio_snd_device_mute_tube) = create_snd_mute_tube_pair()?; 2620*bb4ee6a4SAndroid Build Coastguard Worker 2621*bb4ee6a4SAndroid Build Coastguard Worker let mut initial_audio_session_states: Vec<InitialAudioSessionState> = Vec::new(); 2622*bb4ee6a4SAndroid Build Coastguard Worker 2623*bb4ee6a4SAndroid Build Coastguard Worker let pci_devices = create_devices( 2624*bb4ee6a4SAndroid Build Coastguard Worker &mut cfg, 2625*bb4ee6a4SAndroid Build Coastguard Worker vm.get_memory(), 2626*bb4ee6a4SAndroid Build Coastguard Worker &vm_evt_wrtube, 2627*bb4ee6a4SAndroid Build Coastguard Worker &mut irq_control_tubes, 2628*bb4ee6a4SAndroid Build Coastguard Worker &mut vm_memory_control_tubes, 2629*bb4ee6a4SAndroid Build Coastguard Worker &mut control_tubes, 2630*bb4ee6a4SAndroid Build Coastguard Worker &mut disk_device_tubes, 2631*bb4ee6a4SAndroid Build Coastguard Worker &mut initial_audio_session_states, 2632*bb4ee6a4SAndroid Build Coastguard Worker balloon_device_tube, 2633*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 2634*bb4ee6a4SAndroid Build Coastguard Worker pvclock_device_tube, 2635*bb4ee6a4SAndroid Build Coastguard Worker dynamic_mapping_device_tube, 2636*bb4ee6a4SAndroid Build Coastguard Worker /* inflate_tube= */ None, 2637*bb4ee6a4SAndroid Build Coastguard Worker init_balloon_size, 2638*bb4ee6a4SAndroid Build Coastguard Worker tsc_state.frequency, 2639*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_state_device_tube, 2640*bb4ee6a4SAndroid Build Coastguard Worker virtio_snd_device_mute_tube, 2641*bb4ee6a4SAndroid Build Coastguard Worker )?; 2642*bb4ee6a4SAndroid Build Coastguard Worker 2643*bb4ee6a4SAndroid Build Coastguard Worker let mut vcpu_ids = Vec::new(); 2644*bb4ee6a4SAndroid Build Coastguard Worker 2645*bb4ee6a4SAndroid Build Coastguard Worker let (vwmdt_host_tube, vmwdt_device_tube) = Tube::pair().context("failed to create tube")?; 2646*bb4ee6a4SAndroid Build Coastguard Worker let windows = Arch::build_vm::<V, Vcpu>( 2647*bb4ee6a4SAndroid Build Coastguard Worker components, 2648*bb4ee6a4SAndroid Build Coastguard Worker arch_memory_layout, 2649*bb4ee6a4SAndroid Build Coastguard Worker &vm_evt_wrtube, 2650*bb4ee6a4SAndroid Build Coastguard Worker &mut sys_allocator, 2651*bb4ee6a4SAndroid Build Coastguard Worker &cfg.serial_parameters, 2652*bb4ee6a4SAndroid Build Coastguard Worker None, 2653*bb4ee6a4SAndroid Build Coastguard Worker (cfg.battery_config.as_ref().map(|t| t.type_), None), 2654*bb4ee6a4SAndroid Build Coastguard Worker vm, 2655*bb4ee6a4SAndroid Build Coastguard Worker ramoops_region, 2656*bb4ee6a4SAndroid Build Coastguard Worker pci_devices, 2657*bb4ee6a4SAndroid Build Coastguard Worker irq_chip, 2658*bb4ee6a4SAndroid Build Coastguard Worker &mut vcpu_ids, 2659*bb4ee6a4SAndroid Build Coastguard Worker cfg.dump_device_tree_blob.clone(), 2660*bb4ee6a4SAndroid Build Coastguard Worker /* debugcon_jail= */ None, 2661*bb4ee6a4SAndroid Build Coastguard Worker None, 2662*bb4ee6a4SAndroid Build Coastguard Worker None, 2663*bb4ee6a4SAndroid Build Coastguard Worker /* guest_suspended_cvar= */ None, 2664*bb4ee6a4SAndroid Build Coastguard Worker dt_overlays, 2665*bb4ee6a4SAndroid Build Coastguard Worker cfg.fdt_position, 2666*bb4ee6a4SAndroid Build Coastguard Worker cfg.no_pmu, 2667*bb4ee6a4SAndroid Build Coastguard Worker ) 2668*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::BuildVm, "the architecture failed to build the vm")?; 2669*bb4ee6a4SAndroid Build Coastguard Worker 2670*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] 2671*bb4ee6a4SAndroid Build Coastguard Worker let stats = if cfg.exit_stats { 2672*bb4ee6a4SAndroid Build Coastguard Worker Some(Arc::new(Mutex::new(StatisticsCollector::new()))) 2673*bb4ee6a4SAndroid Build Coastguard Worker } else { 2674*bb4ee6a4SAndroid Build Coastguard Worker None 2675*bb4ee6a4SAndroid Build Coastguard Worker }; 2676*bb4ee6a4SAndroid Build Coastguard Worker 2677*bb4ee6a4SAndroid Build Coastguard Worker run_control( 2678*bb4ee6a4SAndroid Build Coastguard Worker windows, 2679*bb4ee6a4SAndroid Build Coastguard Worker sys_allocator, 2680*bb4ee6a4SAndroid Build Coastguard Worker control_tubes, 2681*bb4ee6a4SAndroid Build Coastguard Worker irq_control_tubes, 2682*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_control_tubes, 2683*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_rdtube, 2684*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube, 2685*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")] 2686*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube, 2687*bb4ee6a4SAndroid Build Coastguard Worker cfg.broker_shutdown_event.take(), 2688*bb4ee6a4SAndroid Build Coastguard Worker balloon_host_tube, 2689*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pvclock")] 2690*bb4ee6a4SAndroid Build Coastguard Worker pvclock_host_tube, 2691*bb4ee6a4SAndroid Build Coastguard Worker disk_host_tubes, 2692*bb4ee6a4SAndroid Build Coastguard Worker initial_audio_session_states, 2693*bb4ee6a4SAndroid Build Coastguard Worker gralloc, 2694*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] 2695*bb4ee6a4SAndroid Build Coastguard Worker stats, 2696*bb4ee6a4SAndroid Build Coastguard Worker cfg.service_pipe_name, 2697*bb4ee6a4SAndroid Build Coastguard Worker vm_memory_size_mb, 2698*bb4ee6a4SAndroid Build Coastguard Worker cfg.host_cpu_topology, 2699*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations, 2700*bb4ee6a4SAndroid Build Coastguard Worker cfg.force_calibrated_tsc_leaf, 2701*bb4ee6a4SAndroid Build Coastguard Worker product_args, 2702*bb4ee6a4SAndroid Build Coastguard Worker match virtio_snd_host_mute_tube { 2703*bb4ee6a4SAndroid Build Coastguard Worker Some(virtio_snd_host_mute_tube) => vec![virtio_snd_host_mute_tube], 2704*bb4ee6a4SAndroid Build Coastguard Worker None => vec![], 2705*bb4ee6a4SAndroid Build Coastguard Worker }, 2706*bb4ee6a4SAndroid Build Coastguard Worker cfg.restore_path, 2707*bb4ee6a4SAndroid Build Coastguard Worker cfg.socket_path, 2708*bb4ee6a4SAndroid Build Coastguard Worker cfg.force_s2idle, 2709*bb4ee6a4SAndroid Build Coastguard Worker cfg.suspended, 2710*bb4ee6a4SAndroid Build Coastguard Worker ) 2711*bb4ee6a4SAndroid Build Coastguard Worker } 2712*bb4ee6a4SAndroid Build Coastguard Worker 2713*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 2714*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 2715*bb4ee6a4SAndroid Build Coastguard Worker use tempfile::TempDir; 2716*bb4ee6a4SAndroid Build Coastguard Worker 2717*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 2718*bb4ee6a4SAndroid Build Coastguard Worker 2719*bb4ee6a4SAndroid Build Coastguard Worker fn create_config(test_dir: &TempDir) -> Config { 2720*bb4ee6a4SAndroid Build Coastguard Worker let mut config = Config::default(); 2721*bb4ee6a4SAndroid Build Coastguard Worker 2722*bb4ee6a4SAndroid Build Coastguard Worker let dummy_kernel_path = test_dir.path().join("dummy_kernel.txt"); 2723*bb4ee6a4SAndroid Build Coastguard Worker OpenOptions::new() 2724*bb4ee6a4SAndroid Build Coastguard Worker .create_new(true) 2725*bb4ee6a4SAndroid Build Coastguard Worker .write(true) 2726*bb4ee6a4SAndroid Build Coastguard Worker .open(&dummy_kernel_path) 2727*bb4ee6a4SAndroid Build Coastguard Worker .expect("Could not open file!"); 2728*bb4ee6a4SAndroid Build Coastguard Worker config.executable_path = Some(Executable::Kernel(dummy_kernel_path)); 2729*bb4ee6a4SAndroid Build Coastguard Worker 2730*bb4ee6a4SAndroid Build Coastguard Worker config 2731*bb4ee6a4SAndroid Build Coastguard Worker } 2732*bb4ee6a4SAndroid Build Coastguard Worker 2733*bb4ee6a4SAndroid Build Coastguard Worker #[test] 2734*bb4ee6a4SAndroid Build Coastguard Worker #[should_panic(expected = "Did not receive a bios or kernel")] 2735*bb4ee6a4SAndroid Build Coastguard Worker fn setup_vm_components_panics_when_no_kernel_provided() { 2736*bb4ee6a4SAndroid Build Coastguard Worker let mut config = 2737*bb4ee6a4SAndroid Build Coastguard Worker create_config(&TempDir::new().expect("Could not create temporary directory!")); 2738*bb4ee6a4SAndroid Build Coastguard Worker config.executable_path = None; 2739*bb4ee6a4SAndroid Build Coastguard Worker let _ = setup_vm_components(&config); 2740*bb4ee6a4SAndroid Build Coastguard Worker } 2741*bb4ee6a4SAndroid Build Coastguard Worker 2742*bb4ee6a4SAndroid Build Coastguard Worker #[test] 2743*bb4ee6a4SAndroid Build Coastguard Worker fn setup_vm_components_stores_memory_in_bytes() { 2744*bb4ee6a4SAndroid Build Coastguard Worker let tempdir = TempDir::new().expect("Could not create temporary directory!"); 2745*bb4ee6a4SAndroid Build Coastguard Worker let mut config = create_config(&tempdir); 2746*bb4ee6a4SAndroid Build Coastguard Worker config.memory = Some(1); 2747*bb4ee6a4SAndroid Build Coastguard Worker let vm_components = setup_vm_components(&config).expect("failed to setup vm components"); 2748*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(vm_components.memory_size, 1024 * 1024); 2749*bb4ee6a4SAndroid Build Coastguard Worker } 2750*bb4ee6a4SAndroid Build Coastguard Worker 2751*bb4ee6a4SAndroid Build Coastguard Worker #[test] 2752*bb4ee6a4SAndroid Build Coastguard Worker fn setup_vm_components_fails_when_memory_too_large() { 2753*bb4ee6a4SAndroid Build Coastguard Worker let tempdir = TempDir::new().expect("Could not create temporary directory!"); 2754*bb4ee6a4SAndroid Build Coastguard Worker let mut config = create_config(&tempdir); 2755*bb4ee6a4SAndroid Build Coastguard Worker // One mb more than a u64 can hold in bytes 2756*bb4ee6a4SAndroid Build Coastguard Worker config.memory = Some((u64::MAX / 1024 / 1024) + 1); 2757*bb4ee6a4SAndroid Build Coastguard Worker setup_vm_components(&config).err().expect("expected error"); 2758*bb4ee6a4SAndroid Build Coastguard Worker } 2759*bb4ee6a4SAndroid Build Coastguard Worker } 2760