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 use std::arch::x86_64::__cpuid;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid_count;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicU64;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Barrier;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::thread;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::thread::JoinHandle;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Instant;
19*bb4ee6a4SAndroid Build Coastguard Worker
20*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
21*bb4ee6a4SAndroid Build Coastguard Worker use aarch64::AArch64 as Arch;
22*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
23*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
24*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result;
25*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuConfigArch;
26*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuSet;
27*bb4ee6a4SAndroid Build Coastguard Worker use arch::IrqChipArch;
28*bb4ee6a4SAndroid Build Coastguard Worker use arch::LinuxArch;
29*bb4ee6a4SAndroid Build Coastguard Worker use arch::RunnableLinuxVm;
30*bb4ee6a4SAndroid Build Coastguard Worker use arch::VcpuAffinity;
31*bb4ee6a4SAndroid Build Coastguard Worker use arch::VcpuArch;
32*bb4ee6a4SAndroid Build Coastguard Worker use arch::VmArch;
33*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
34*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
35*bb4ee6a4SAndroid Build Coastguard Worker use base::set_audio_thread_priority;
36*bb4ee6a4SAndroid Build Coastguard Worker use base::set_cpu_affinity;
37*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
38*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
39*bb4ee6a4SAndroid Build Coastguard Worker use base::Result as BaseResult;
40*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeMultimediaHandle;
41*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
42*bb4ee6a4SAndroid Build Coastguard Worker use base::Timer;
43*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
44*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
45*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::select2;
46*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::EventAsync;
47*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::Executor;
48*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::SelectResult;
49*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::TimerAsync;
50*bb4ee6a4SAndroid Build Coastguard Worker use cros_tracing::trace_event;
51*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::bail_exit_code;
52*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::Exit;
53*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::ExitContext;
54*bb4ee6a4SAndroid Build Coastguard Worker use crosvm_cli::sys::windows::exit::ExitContextAnyhow;
55*bb4ee6a4SAndroid Build Coastguard Worker use devices::tsc::TscSyncMitigations;
56*bb4ee6a4SAndroid Build Coastguard Worker use devices::Bus;
57*bb4ee6a4SAndroid Build Coastguard Worker use devices::VcpuRunState;
58*bb4ee6a4SAndroid Build Coastguard Worker use futures::pin_mut;
59*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")]
60*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxVcpu;
61*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
62*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::CpuConfigX86_64;
63*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorCap;
64*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoEventAddress;
65*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoOperation;
66*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoParams;
67*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuExit;
68*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuInitX86_64;
69*bb4ee6a4SAndroid Build Coastguard Worker use metrics_events::MetricEventType;
70*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
71*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
72*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VcpuControl;
73*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRunMode;
74*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::winerror::ERROR_RETRY;
75*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
76*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::cpuid::adjust_cpuid;
77*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
78*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::cpuid::CpuIdContext;
79*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
80*bb4ee6a4SAndroid Build Coastguard Worker use x86_64::X8664arch as Arch;
81*bb4ee6a4SAndroid Build Coastguard Worker
82*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
83*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::sys::windows::stats::StatisticsCollector;
84*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
85*bb4ee6a4SAndroid Build Coastguard Worker use crate::crosvm::sys::windows::stats::VmExitStatistics;
86*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::save_vcpu_tsc_offset;
87*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::windows::ExitState;
88*bb4ee6a4SAndroid Build Coastguard Worker
89*bb4ee6a4SAndroid Build Coastguard Worker const ERROR_RETRY_I32: i32 = ERROR_RETRY as i32;
90*bb4ee6a4SAndroid Build Coastguard Worker
91*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
92*bb4ee6a4SAndroid Build Coastguard Worker pub struct VcpuRunMode {
93*bb4ee6a4SAndroid Build Coastguard Worker mtx: Mutex<VmRunMode>,
94*bb4ee6a4SAndroid Build Coastguard Worker cvar: Condvar,
95*bb4ee6a4SAndroid Build Coastguard Worker }
96*bb4ee6a4SAndroid Build Coastguard Worker
97*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuRunMode {
get_mode(&self) -> VmRunMode98*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_mode(&self) -> VmRunMode {
99*bb4ee6a4SAndroid Build Coastguard Worker *self.mtx.lock()
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker
set_and_notify(&self, new_mode: VmRunMode)102*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_and_notify(&self, new_mode: VmRunMode) {
103*bb4ee6a4SAndroid Build Coastguard Worker *self.mtx.lock() = new_mode;
104*bb4ee6a4SAndroid Build Coastguard Worker self.cvar.notify_all();
105*bb4ee6a4SAndroid Build Coastguard Worker }
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker
108*bb4ee6a4SAndroid Build Coastguard Worker struct RunnableVcpuInfo<V> {
109*bb4ee6a4SAndroid Build Coastguard Worker vcpu: V,
110*bb4ee6a4SAndroid Build Coastguard Worker thread_priority_handle: Option<SafeMultimediaHandle>,
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker
113*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug)]
114*bb4ee6a4SAndroid Build Coastguard Worker struct VcpuMonitoringMetadata {
115*bb4ee6a4SAndroid Build Coastguard Worker pub start_instant: Instant,
116*bb4ee6a4SAndroid Build Coastguard Worker // Milliseconds since the baseline start_instant
117*bb4ee6a4SAndroid Build Coastguard Worker pub last_run_time: Arc<AtomicU64>,
118*bb4ee6a4SAndroid Build Coastguard Worker pub last_exit_snapshot: Arc<Mutex<Option<VcpuExitData>>>,
119*bb4ee6a4SAndroid Build Coastguard Worker }
120*bb4ee6a4SAndroid Build Coastguard Worker
121*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug)]
122*bb4ee6a4SAndroid Build Coastguard Worker struct VcpuRunThread {
123*bb4ee6a4SAndroid Build Coastguard Worker pub cpu_id: usize,
124*bb4ee6a4SAndroid Build Coastguard Worker pub monitoring_metadata: Option<VcpuMonitoringMetadata>,
125*bb4ee6a4SAndroid Build Coastguard Worker }
126*bb4ee6a4SAndroid Build Coastguard Worker
127*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuRunThread {
new(cpu_id: usize, enable_vcpu_monitoring: bool) -> VcpuRunThread128*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(cpu_id: usize, enable_vcpu_monitoring: bool) -> VcpuRunThread {
129*bb4ee6a4SAndroid Build Coastguard Worker VcpuRunThread {
130*bb4ee6a4SAndroid Build Coastguard Worker cpu_id,
131*bb4ee6a4SAndroid Build Coastguard Worker monitoring_metadata: enable_vcpu_monitoring.then(|| VcpuMonitoringMetadata {
132*bb4ee6a4SAndroid Build Coastguard Worker start_instant: Instant::now(),
133*bb4ee6a4SAndroid Build Coastguard Worker last_run_time: Arc::new(AtomicU64::new(0)),
134*bb4ee6a4SAndroid Build Coastguard Worker last_exit_snapshot: Arc::new(Mutex::new(Option::None)),
135*bb4ee6a4SAndroid Build Coastguard Worker }),
136*bb4ee6a4SAndroid Build Coastguard Worker }
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker
139*bb4ee6a4SAndroid Build Coastguard Worker /// Perform WHPX-specific vcpu configurations
140*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")]
whpx_configure_vcpu(vcpu: &mut dyn VcpuArch, irq_chip: &mut dyn IrqChipArch)141*bb4ee6a4SAndroid Build Coastguard Worker fn whpx_configure_vcpu(vcpu: &mut dyn VcpuArch, irq_chip: &mut dyn IrqChipArch) {
142*bb4ee6a4SAndroid Build Coastguard Worker // only apply to actual WhpxVcpu instances
143*bb4ee6a4SAndroid Build Coastguard Worker if let Some(whpx_vcpu) = vcpu.downcast_mut::<WhpxVcpu>() {
144*bb4ee6a4SAndroid Build Coastguard Worker // WhpxVcpu instances need to know the TSC and Lapic frequencies to handle Hyper-V MSR
145*bb4ee6a4SAndroid Build Coastguard Worker // reads and writes.
146*bb4ee6a4SAndroid Build Coastguard Worker let tsc_freq = devices::tsc::tsc_frequency()
147*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| {
148*bb4ee6a4SAndroid Build Coastguard Worker error!(
149*bb4ee6a4SAndroid Build Coastguard Worker "Could not determine TSC frequency, WHPX vcpu will not be configured with \
150*bb4ee6a4SAndroid Build Coastguard Worker a TSC Frequency: {e}"
151*bb4ee6a4SAndroid Build Coastguard Worker );
152*bb4ee6a4SAndroid Build Coastguard Worker e
153*bb4ee6a4SAndroid Build Coastguard Worker })
154*bb4ee6a4SAndroid Build Coastguard Worker .ok();
155*bb4ee6a4SAndroid Build Coastguard Worker whpx_vcpu.set_frequencies(tsc_freq, irq_chip.lapic_frequency());
156*bb4ee6a4SAndroid Build Coastguard Worker }
157*bb4ee6a4SAndroid Build Coastguard Worker }
158*bb4ee6a4SAndroid Build Coastguard Worker
159*bb4ee6a4SAndroid Build Coastguard Worker // Sets up a vcpu and converts it into a runnable vcpu.
runnable_vcpu<V>( cpu_id: usize, vcpu: Option<V>, vcpu_init: VcpuInitX86_64, vm: &impl VmArch, irq_chip: &mut dyn IrqChipArch, vcpu_count: usize, run_rt: bool, vcpu_affinity: Option<CpuSet>, no_smt: bool, host_cpu_topology: bool, force_calibrated_tsc_leaf: bool, ) -> Result<RunnableVcpuInfo<V>> where V: VcpuArch,160*bb4ee6a4SAndroid Build Coastguard Worker fn runnable_vcpu<V>(
161*bb4ee6a4SAndroid Build Coastguard Worker cpu_id: usize,
162*bb4ee6a4SAndroid Build Coastguard Worker vcpu: Option<V>,
163*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init: VcpuInitX86_64,
164*bb4ee6a4SAndroid Build Coastguard Worker vm: &impl VmArch,
165*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: &mut dyn IrqChipArch,
166*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count: usize,
167*bb4ee6a4SAndroid Build Coastguard Worker run_rt: bool,
168*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity: Option<CpuSet>,
169*bb4ee6a4SAndroid Build Coastguard Worker no_smt: bool,
170*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology: bool,
171*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf: bool,
172*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<RunnableVcpuInfo<V>>
173*bb4ee6a4SAndroid Build Coastguard Worker where
174*bb4ee6a4SAndroid Build Coastguard Worker V: VcpuArch,
175*bb4ee6a4SAndroid Build Coastguard Worker {
176*bb4ee6a4SAndroid Build Coastguard Worker let mut vcpu = match vcpu {
177*bb4ee6a4SAndroid Build Coastguard Worker Some(v) => v,
178*bb4ee6a4SAndroid Build Coastguard Worker None => {
179*bb4ee6a4SAndroid Build Coastguard Worker // If vcpu is None, it means this arch/hypervisor requires create_vcpu to be called
180*bb4ee6a4SAndroid Build Coastguard Worker // from the vcpu thread.
181*bb4ee6a4SAndroid Build Coastguard Worker match vm
182*bb4ee6a4SAndroid Build Coastguard Worker .create_vcpu(cpu_id)
183*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CreateVcpu, "failed to create vcpu")?
184*bb4ee6a4SAndroid Build Coastguard Worker .downcast::<V>()
185*bb4ee6a4SAndroid Build Coastguard Worker {
186*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => *v,
187*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("VM created wrong type of VCPU"),
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker };
191*bb4ee6a4SAndroid Build Coastguard Worker
192*bb4ee6a4SAndroid Build Coastguard Worker irq_chip
193*bb4ee6a4SAndroid Build Coastguard Worker .add_vcpu(cpu_id, &vcpu)
194*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::AddIrqChipVcpu, "failed to add vcpu to irq chip")?;
195*bb4ee6a4SAndroid Build Coastguard Worker
196*bb4ee6a4SAndroid Build Coastguard Worker if let Some(affinity) = vcpu_affinity {
197*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = set_cpu_affinity(affinity) {
198*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to set CPU affinity: {}", e);
199*bb4ee6a4SAndroid Build Coastguard Worker }
200*bb4ee6a4SAndroid Build Coastguard Worker }
201*bb4ee6a4SAndroid Build Coastguard Worker
202*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
203*bb4ee6a4SAndroid Build Coastguard Worker let cpu_config = Some(CpuConfigX86_64::new(
204*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf,
205*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology,
206*bb4ee6a4SAndroid Build Coastguard Worker false, /* enable_hwp */
207*bb4ee6a4SAndroid Build Coastguard Worker no_smt,
208*bb4ee6a4SAndroid Build Coastguard Worker false, /* itmt */
209*bb4ee6a4SAndroid Build Coastguard Worker None, /* hybrid_type */
210*bb4ee6a4SAndroid Build Coastguard Worker ));
211*bb4ee6a4SAndroid Build Coastguard Worker
212*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
213*bb4ee6a4SAndroid Build Coastguard Worker let cpu_config = None;
214*bb4ee6a4SAndroid Build Coastguard Worker
215*bb4ee6a4SAndroid Build Coastguard Worker Arch::configure_vcpu(
216*bb4ee6a4SAndroid Build Coastguard Worker vm,
217*bb4ee6a4SAndroid Build Coastguard Worker vm.get_hypervisor(),
218*bb4ee6a4SAndroid Build Coastguard Worker irq_chip,
219*bb4ee6a4SAndroid Build Coastguard Worker &mut vcpu,
220*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init,
221*bb4ee6a4SAndroid Build Coastguard Worker cpu_id,
222*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count,
223*bb4ee6a4SAndroid Build Coastguard Worker cpu_config,
224*bb4ee6a4SAndroid Build Coastguard Worker )
225*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::ConfigureVcpu, "failed to configure vcpu")?;
226*bb4ee6a4SAndroid Build Coastguard Worker
227*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "whpx")]
228*bb4ee6a4SAndroid Build Coastguard Worker Self::whpx_configure_vcpu(&mut vcpu, irq_chip);
229*bb4ee6a4SAndroid Build Coastguard Worker
230*bb4ee6a4SAndroid Build Coastguard Worker let mut thread_priority_handle = None;
231*bb4ee6a4SAndroid Build Coastguard Worker if run_rt {
232*bb4ee6a4SAndroid Build Coastguard Worker // Until we are multi process on Windows, we can't use the normal thread priority APIs;
233*bb4ee6a4SAndroid Build Coastguard Worker // instead, we use a trick from the audio device which is able to set a thread RT even
234*bb4ee6a4SAndroid Build Coastguard Worker // though the process itself is not RT.
235*bb4ee6a4SAndroid Build Coastguard Worker thread_priority_handle = match set_audio_thread_priority() {
236*bb4ee6a4SAndroid Build Coastguard Worker Ok(hndl) => Some(hndl),
237*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
238*bb4ee6a4SAndroid Build Coastguard Worker warn!("Failed to set vcpu thread to real time priority: {}", e);
239*bb4ee6a4SAndroid Build Coastguard Worker None
240*bb4ee6a4SAndroid Build Coastguard Worker }
241*bb4ee6a4SAndroid Build Coastguard Worker };
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker
244*bb4ee6a4SAndroid Build Coastguard Worker Ok(RunnableVcpuInfo {
245*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
246*bb4ee6a4SAndroid Build Coastguard Worker thread_priority_handle,
247*bb4ee6a4SAndroid Build Coastguard Worker })
248*bb4ee6a4SAndroid Build Coastguard Worker }
249*bb4ee6a4SAndroid Build Coastguard Worker
run<V>( &self, vcpu: Option<V>, vcpu_init: VcpuInitX86_64, vcpus: Arc<Mutex<Vec<Box<dyn VcpuArch>>>>, vm: impl VmArch + 'static, mut irq_chip: Box<dyn IrqChipArch + 'static>, vcpu_count: usize, run_rt: bool, vcpu_affinity: Option<CpuSet>, delay_rt: bool, no_smt: bool, start_barrier: Arc<Barrier>, vcpu_create_barrier: Arc<Barrier>, mut io_bus: devices::Bus, mut mmio_bus: devices::Bus, vm_evt_wrtube: SendTube, run_mode_arc: Arc<VcpuRunMode>, #[cfg(feature = "stats")] stats: Option<Arc<Mutex<StatisticsCollector>>>, host_cpu_topology: bool, tsc_offset: Option<u64>, force_calibrated_tsc_leaf: bool, vcpu_control: mpsc::Receiver<VcpuControl>, ) -> Result<JoinHandle<Result<()>>> where V: VcpuArch + 'static,250*bb4ee6a4SAndroid Build Coastguard Worker pub fn run<V>(
251*bb4ee6a4SAndroid Build Coastguard Worker &self,
252*bb4ee6a4SAndroid Build Coastguard Worker vcpu: Option<V>,
253*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init: VcpuInitX86_64,
254*bb4ee6a4SAndroid Build Coastguard Worker vcpus: Arc<Mutex<Vec<Box<dyn VcpuArch>>>>,
255*bb4ee6a4SAndroid Build Coastguard Worker vm: impl VmArch + 'static,
256*bb4ee6a4SAndroid Build Coastguard Worker mut irq_chip: Box<dyn IrqChipArch + 'static>,
257*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count: usize,
258*bb4ee6a4SAndroid Build Coastguard Worker run_rt: bool,
259*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity: Option<CpuSet>,
260*bb4ee6a4SAndroid Build Coastguard Worker delay_rt: bool,
261*bb4ee6a4SAndroid Build Coastguard Worker no_smt: bool,
262*bb4ee6a4SAndroid Build Coastguard Worker start_barrier: Arc<Barrier>,
263*bb4ee6a4SAndroid Build Coastguard Worker vcpu_create_barrier: Arc<Barrier>,
264*bb4ee6a4SAndroid Build Coastguard Worker mut io_bus: devices::Bus,
265*bb4ee6a4SAndroid Build Coastguard Worker mut mmio_bus: devices::Bus,
266*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: SendTube,
267*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc: Arc<VcpuRunMode>,
268*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] stats: Option<Arc<Mutex<StatisticsCollector>>>,
269*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology: bool,
270*bb4ee6a4SAndroid Build Coastguard Worker tsc_offset: Option<u64>,
271*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf: bool,
272*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control: mpsc::Receiver<VcpuControl>,
273*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<JoinHandle<Result<()>>>
274*bb4ee6a4SAndroid Build Coastguard Worker where
275*bb4ee6a4SAndroid Build Coastguard Worker V: VcpuArch + 'static,
276*bb4ee6a4SAndroid Build Coastguard Worker {
277*bb4ee6a4SAndroid Build Coastguard Worker let context = self.clone();
278*bb4ee6a4SAndroid Build Coastguard Worker thread::Builder::new()
279*bb4ee6a4SAndroid Build Coastguard Worker .name(format!("crosvm_vcpu{}", self.cpu_id))
280*bb4ee6a4SAndroid Build Coastguard Worker .spawn(move || {
281*bb4ee6a4SAndroid Build Coastguard Worker // Having a closure returning ExitState guarentees that we
282*bb4ee6a4SAndroid Build Coastguard Worker // send a VmEventType on all code paths after the closure
283*bb4ee6a4SAndroid Build Coastguard Worker // returns.
284*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_fn = || -> Result<ExitState> {
285*bb4ee6a4SAndroid Build Coastguard Worker let runnable_vcpu = Self::runnable_vcpu(
286*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id,
287*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
288*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init,
289*bb4ee6a4SAndroid Build Coastguard Worker &vm,
290*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.as_mut(),
291*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count,
292*bb4ee6a4SAndroid Build Coastguard Worker run_rt && !delay_rt,
293*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity,
294*bb4ee6a4SAndroid Build Coastguard Worker no_smt,
295*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology,
296*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf,
297*bb4ee6a4SAndroid Build Coastguard Worker );
298*bb4ee6a4SAndroid Build Coastguard Worker
299*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
300*bb4ee6a4SAndroid Build Coastguard Worker let cpu_config = CpuConfigX86_64::new(
301*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf,
302*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology,
303*bb4ee6a4SAndroid Build Coastguard Worker false, /* enable_hwp */
304*bb4ee6a4SAndroid Build Coastguard Worker no_smt,
305*bb4ee6a4SAndroid Build Coastguard Worker false, /* itmt */
306*bb4ee6a4SAndroid Build Coastguard Worker None, /* hybrid_type */
307*bb4ee6a4SAndroid Build Coastguard Worker );
308*bb4ee6a4SAndroid Build Coastguard Worker
309*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
310*bb4ee6a4SAndroid Build Coastguard Worker let cpuid_context = CpuIdContext::new(
311*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id,
312*bb4ee6a4SAndroid Build Coastguard Worker vcpu_count,
313*bb4ee6a4SAndroid Build Coastguard Worker Some(irq_chip.as_ref()),
314*bb4ee6a4SAndroid Build Coastguard Worker cpu_config,
315*bb4ee6a4SAndroid Build Coastguard Worker vm.get_hypervisor()
316*bb4ee6a4SAndroid Build Coastguard Worker .check_capability(HypervisorCap::CalibratedTscLeafRequired),
317*bb4ee6a4SAndroid Build Coastguard Worker __cpuid_count,
318*bb4ee6a4SAndroid Build Coastguard Worker __cpuid,
319*bb4ee6a4SAndroid Build Coastguard Worker );
320*bb4ee6a4SAndroid Build Coastguard Worker
321*bb4ee6a4SAndroid Build Coastguard Worker // The vcpu_create_barrier is supplied from the main thread in order for it to
322*bb4ee6a4SAndroid Build Coastguard Worker // wait until this thread is done creating its vcpu.
323*bb4ee6a4SAndroid Build Coastguard Worker vcpu_create_barrier.wait();
324*bb4ee6a4SAndroid Build Coastguard Worker
325*bb4ee6a4SAndroid Build Coastguard Worker // Wait for this barrier before continuing forward.
326*bb4ee6a4SAndroid Build Coastguard Worker start_barrier.wait();
327*bb4ee6a4SAndroid Build Coastguard Worker
328*bb4ee6a4SAndroid Build Coastguard Worker let RunnableVcpuInfo {
329*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
330*bb4ee6a4SAndroid Build Coastguard Worker thread_priority_handle: _thread_priority_handle,
331*bb4ee6a4SAndroid Build Coastguard Worker } = runnable_vcpu?;
332*bb4ee6a4SAndroid Build Coastguard Worker
333*bb4ee6a4SAndroid Build Coastguard Worker if let Some(offset) = tsc_offset {
334*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_tsc_offset(offset).unwrap_or_else(|e| {
335*bb4ee6a4SAndroid Build Coastguard Worker error!(
336*bb4ee6a4SAndroid Build Coastguard Worker "Failed to set tsc_offset of {} on vcpu {}: {}",
337*bb4ee6a4SAndroid Build Coastguard Worker offset, context.cpu_id, e
338*bb4ee6a4SAndroid Build Coastguard Worker )
339*bb4ee6a4SAndroid Build Coastguard Worker });
340*bb4ee6a4SAndroid Build Coastguard Worker }
341*bb4ee6a4SAndroid Build Coastguard Worker
342*bb4ee6a4SAndroid Build Coastguard Worker // Clone vcpu so it can be used by the main thread to force a vcpu run to exit
343*bb4ee6a4SAndroid Build Coastguard Worker vcpus
344*bb4ee6a4SAndroid Build Coastguard Worker .lock()
345*bb4ee6a4SAndroid Build Coastguard Worker .push(Box::new(vcpu.try_clone().expect("Could not clone vcpu!")));
346*bb4ee6a4SAndroid Build Coastguard Worker
347*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus.set_access_id(context.cpu_id);
348*bb4ee6a4SAndroid Build Coastguard Worker io_bus.set_access_id(context.cpu_id);
349*bb4ee6a4SAndroid Build Coastguard Worker
350*bb4ee6a4SAndroid Build Coastguard Worker vcpu_loop(
351*bb4ee6a4SAndroid Build Coastguard Worker &context,
352*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
353*bb4ee6a4SAndroid Build Coastguard Worker vm,
354*bb4ee6a4SAndroid Build Coastguard Worker irq_chip,
355*bb4ee6a4SAndroid Build Coastguard Worker io_bus,
356*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus,
357*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc,
358*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
359*bb4ee6a4SAndroid Build Coastguard Worker stats,
360*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
361*bb4ee6a4SAndroid Build Coastguard Worker cpuid_context,
362*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control,
363*bb4ee6a4SAndroid Build Coastguard Worker )
364*bb4ee6a4SAndroid Build Coastguard Worker };
365*bb4ee6a4SAndroid Build Coastguard Worker
366*bb4ee6a4SAndroid Build Coastguard Worker let exit_state = vcpu_fn().unwrap_or_else(|e| {
367*bb4ee6a4SAndroid Build Coastguard Worker error!(
368*bb4ee6a4SAndroid Build Coastguard Worker "vcpu {} run loop exited with error: {:#}",
369*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id, e
370*bb4ee6a4SAndroid Build Coastguard Worker );
371*bb4ee6a4SAndroid Build Coastguard Worker ExitState::Stop
372*bb4ee6a4SAndroid Build Coastguard Worker });
373*bb4ee6a4SAndroid Build Coastguard Worker
374*bb4ee6a4SAndroid Build Coastguard Worker let final_event_data = match exit_state {
375*bb4ee6a4SAndroid Build Coastguard Worker ExitState::Stop => VmEventType::Exit,
376*bb4ee6a4SAndroid Build Coastguard Worker _ => unreachable!(),
377*bb4ee6a4SAndroid Build Coastguard Worker };
378*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube
379*bb4ee6a4SAndroid Build Coastguard Worker .send::<VmEventType>(&final_event_data)
380*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| {
381*bb4ee6a4SAndroid Build Coastguard Worker error!(
382*bb4ee6a4SAndroid Build Coastguard Worker "failed to send final event {:?} on vcpu {}: {}",
383*bb4ee6a4SAndroid Build Coastguard Worker final_event_data, context.cpu_id, e
384*bb4ee6a4SAndroid Build Coastguard Worker )
385*bb4ee6a4SAndroid Build Coastguard Worker });
386*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
387*bb4ee6a4SAndroid Build Coastguard Worker })
388*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::SpawnVcpu, "failed to spawn VCPU thread")
389*bb4ee6a4SAndroid Build Coastguard Worker }
390*bb4ee6a4SAndroid Build Coastguard Worker }
391*bb4ee6a4SAndroid Build Coastguard Worker
392*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug)]
393*bb4ee6a4SAndroid Build Coastguard Worker struct VcpuExitData {
394*bb4ee6a4SAndroid Build Coastguard Worker // Represented by duration since baseline start_instant
395*bb4ee6a4SAndroid Build Coastguard Worker exit_time: Duration,
396*bb4ee6a4SAndroid Build Coastguard Worker exit_result: BaseResult<VcpuExit>,
397*bb4ee6a4SAndroid Build Coastguard Worker }
398*bb4ee6a4SAndroid Build Coastguard Worker
399*bb4ee6a4SAndroid Build Coastguard Worker impl Display for VcpuExitData {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result400*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401*bb4ee6a4SAndroid Build Coastguard Worker write!(f, "exit result: {:?}", self.exit_result)
402*bb4ee6a4SAndroid Build Coastguard Worker }
403*bb4ee6a4SAndroid Build Coastguard Worker }
404*bb4ee6a4SAndroid Build Coastguard Worker
405*bb4ee6a4SAndroid Build Coastguard Worker struct VcpuStallMonitor {
406*bb4ee6a4SAndroid Build Coastguard Worker vcpu_run_threads: Vec<VcpuRunThread>,
407*bb4ee6a4SAndroid Build Coastguard Worker run_mode: Arc<VcpuRunMode>,
408*bb4ee6a4SAndroid Build Coastguard Worker }
409*bb4ee6a4SAndroid Build Coastguard Worker
410*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuStallMonitor {
411*bb4ee6a4SAndroid Build Coastguard Worker const HOST_STALL_TIMEOUT: Duration = Duration::from_secs(2);
412*bb4ee6a4SAndroid Build Coastguard Worker const VCPU_CHECKUP_INTERVAL: Duration = Duration::from_secs(1);
413*bb4ee6a4SAndroid Build Coastguard Worker const STALL_REPORTING_LIMITER: Duration = Duration::from_secs(10);
414*bb4ee6a4SAndroid Build Coastguard Worker
init(run_mode: Arc<VcpuRunMode>) -> VcpuStallMonitor415*bb4ee6a4SAndroid Build Coastguard Worker pub fn init(run_mode: Arc<VcpuRunMode>) -> VcpuStallMonitor {
416*bb4ee6a4SAndroid Build Coastguard Worker VcpuStallMonitor {
417*bb4ee6a4SAndroid Build Coastguard Worker vcpu_run_threads: vec![],
418*bb4ee6a4SAndroid Build Coastguard Worker run_mode,
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker }
421*bb4ee6a4SAndroid Build Coastguard Worker
add_vcpu_thread(&mut self, thread: VcpuRunThread)422*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_vcpu_thread(&mut self, thread: VcpuRunThread) {
423*bb4ee6a4SAndroid Build Coastguard Worker self.vcpu_run_threads.push(thread);
424*bb4ee6a4SAndroid Build Coastguard Worker }
425*bb4ee6a4SAndroid Build Coastguard Worker
run(self, exit_event: &Event) -> Result<JoinHandle<Result<()>>>426*bb4ee6a4SAndroid Build Coastguard Worker pub fn run(self, exit_event: &Event) -> Result<JoinHandle<Result<()>>> {
427*bb4ee6a4SAndroid Build Coastguard Worker let cloned_exit_event = exit_event
428*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
429*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CloneEvent, "failed to clone event")?;
430*bb4ee6a4SAndroid Build Coastguard Worker thread::Builder::new()
431*bb4ee6a4SAndroid Build Coastguard Worker .name("crosvm_vcpu_stall_monitor".to_string())
432*bb4ee6a4SAndroid Build Coastguard Worker .spawn(move || {
433*bb4ee6a4SAndroid Build Coastguard Worker let ex = Executor::new()?;
434*bb4ee6a4SAndroid Build Coastguard Worker
435*bb4ee6a4SAndroid Build Coastguard Worker let mut timer = TimerAsync::new(Timer::new()?, &ex)?;
436*bb4ee6a4SAndroid Build Coastguard Worker let mut reset_timer = true;
437*bb4ee6a4SAndroid Build Coastguard Worker
438*bb4ee6a4SAndroid Build Coastguard Worker let exit_evt_async = EventAsync::new(cloned_exit_event, &ex)?;
439*bb4ee6a4SAndroid Build Coastguard Worker let exit_future = exit_evt_async.next_val();
440*bb4ee6a4SAndroid Build Coastguard Worker pin_mut!(exit_future);
441*bb4ee6a4SAndroid Build Coastguard Worker 'main: loop {
442*bb4ee6a4SAndroid Build Coastguard Worker if reset_timer {
443*bb4ee6a4SAndroid Build Coastguard Worker timer.reset_repeating(Self::VCPU_CHECKUP_INTERVAL)?;
444*bb4ee6a4SAndroid Build Coastguard Worker reset_timer = false;
445*bb4ee6a4SAndroid Build Coastguard Worker }
446*bb4ee6a4SAndroid Build Coastguard Worker let timer_future = timer.wait();
447*bb4ee6a4SAndroid Build Coastguard Worker pin_mut!(timer_future);
448*bb4ee6a4SAndroid Build Coastguard Worker match ex.run_until(select2(timer_future, exit_future)) {
449*bb4ee6a4SAndroid Build Coastguard Worker Ok((timer_result, exit_result)) => {
450*bb4ee6a4SAndroid Build Coastguard Worker match exit_result {
451*bb4ee6a4SAndroid Build Coastguard Worker SelectResult::Finished(_) => {
452*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu monitor got exit event");
453*bb4ee6a4SAndroid Build Coastguard Worker break 'main;
454*bb4ee6a4SAndroid Build Coastguard Worker }
455*bb4ee6a4SAndroid Build Coastguard Worker SelectResult::Pending(future) => exit_future = future,
456*bb4ee6a4SAndroid Build Coastguard Worker }
457*bb4ee6a4SAndroid Build Coastguard Worker
458*bb4ee6a4SAndroid Build Coastguard Worker match timer_result {
459*bb4ee6a4SAndroid Build Coastguard Worker SelectResult::Finished(Err(e)) => {
460*bb4ee6a4SAndroid Build Coastguard Worker error!(
461*bb4ee6a4SAndroid Build Coastguard Worker "vcpu monitor aborting due to error awaiting future: {}",
462*bb4ee6a4SAndroid Build Coastguard Worker e
463*bb4ee6a4SAndroid Build Coastguard Worker );
464*bb4ee6a4SAndroid Build Coastguard Worker break 'main;
465*bb4ee6a4SAndroid Build Coastguard Worker }
466*bb4ee6a4SAndroid Build Coastguard Worker SelectResult::Finished(_) => self.report_any_stalls(),
467*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
468*bb4ee6a4SAndroid Build Coastguard Worker }
469*bb4ee6a4SAndroid Build Coastguard Worker }
470*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
471*bb4ee6a4SAndroid Build Coastguard Worker error!("vcpu monitor failed to wait on future set: {:?}", e);
472*bb4ee6a4SAndroid Build Coastguard Worker break 'main;
473*bb4ee6a4SAndroid Build Coastguard Worker }
474*bb4ee6a4SAndroid Build Coastguard Worker }
475*bb4ee6a4SAndroid Build Coastguard Worker
476*bb4ee6a4SAndroid Build Coastguard Worker // Always ensure the vcpus aren't suspended before continuing to montior.
477*bb4ee6a4SAndroid Build Coastguard Worker let mut run_mode_lock = self.run_mode.mtx.lock();
478*bb4ee6a4SAndroid Build Coastguard Worker loop {
479*bb4ee6a4SAndroid Build Coastguard Worker match *run_mode_lock {
480*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Running => break,
481*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Suspending | VmRunMode::Breakpoint => {
482*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu monitor pausing until end of suspension");
483*bb4ee6a4SAndroid Build Coastguard Worker run_mode_lock = self.run_mode.cvar.wait(run_mode_lock);
484*bb4ee6a4SAndroid Build Coastguard Worker reset_timer = true;
485*bb4ee6a4SAndroid Build Coastguard Worker }
486*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Exiting => {
487*bb4ee6a4SAndroid Build Coastguard Worker info!("vcpu monitor detected vm exit");
488*bb4ee6a4SAndroid Build Coastguard Worker break 'main;
489*bb4ee6a4SAndroid Build Coastguard Worker }
490*bb4ee6a4SAndroid Build Coastguard Worker }
491*bb4ee6a4SAndroid Build Coastguard Worker }
492*bb4ee6a4SAndroid Build Coastguard Worker }
493*bb4ee6a4SAndroid Build Coastguard Worker
494*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
495*bb4ee6a4SAndroid Build Coastguard Worker })
496*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(
497*bb4ee6a4SAndroid Build Coastguard Worker Exit::SpawnVcpuMonitor,
498*bb4ee6a4SAndroid Build Coastguard Worker "failed to spawn VCPU stall monitor thread",
499*bb4ee6a4SAndroid Build Coastguard Worker )
500*bb4ee6a4SAndroid Build Coastguard Worker }
501*bb4ee6a4SAndroid Build Coastguard Worker
report_any_stalls(&self)502*bb4ee6a4SAndroid Build Coastguard Worker fn report_any_stalls(&self) {
503*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/208267651): Add and fire Clearcut events for stalls (and add tests)
504*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/208267651): Also test guest stalls (vcpu.run() goes too long without exiting)
505*bb4ee6a4SAndroid Build Coastguard Worker let now = Instant::now();
506*bb4ee6a4SAndroid Build Coastguard Worker for vcpu_thread in self.vcpu_run_threads.iter() {
507*bb4ee6a4SAndroid Build Coastguard Worker let monitoring_metadata = vcpu_thread.monitoring_metadata.as_ref().unwrap();
508*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref exit_snapshot) = monitoring_metadata.last_exit_snapshot.lock().clone() {
509*bb4ee6a4SAndroid Build Coastguard Worker let last_run =
510*bb4ee6a4SAndroid Build Coastguard Worker Duration::from_millis(monitoring_metadata.last_run_time.load(Ordering::SeqCst));
511*bb4ee6a4SAndroid Build Coastguard Worker if last_run < exit_snapshot.exit_time {
512*bb4ee6a4SAndroid Build Coastguard Worker // VCPU is between runs
513*bb4ee6a4SAndroid Build Coastguard Worker let time_since_exit = now.saturating_duration_since(
514*bb4ee6a4SAndroid Build Coastguard Worker monitoring_metadata.start_instant + exit_snapshot.exit_time,
515*bb4ee6a4SAndroid Build Coastguard Worker );
516*bb4ee6a4SAndroid Build Coastguard Worker if time_since_exit > Self::HOST_STALL_TIMEOUT {
517*bb4ee6a4SAndroid Build Coastguard Worker self.report_stall(vcpu_thread.cpu_id, exit_snapshot, time_since_exit);
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker }
520*bb4ee6a4SAndroid Build Coastguard Worker };
521*bb4ee6a4SAndroid Build Coastguard Worker }
522*bb4ee6a4SAndroid Build Coastguard Worker }
523*bb4ee6a4SAndroid Build Coastguard Worker
report_stall(&self, cpu_id: usize, exit_data: &VcpuExitData, stall_time: Duration)524*bb4ee6a4SAndroid Build Coastguard Worker fn report_stall(&self, cpu_id: usize, exit_data: &VcpuExitData, stall_time: Duration) {
525*bb4ee6a4SAndroid Build Coastguard Worker if stall_time > Self::STALL_REPORTING_LIMITER {
526*bb4ee6a4SAndroid Build Coastguard Worker return;
527*bb4ee6a4SAndroid Build Coastguard Worker }
528*bb4ee6a4SAndroid Build Coastguard Worker // Double check the Vm is running. We don't care about stalls during suspension/exit
529*bb4ee6a4SAndroid Build Coastguard Worker if *self.run_mode.mtx.lock() != VmRunMode::Running {
530*bb4ee6a4SAndroid Build Coastguard Worker let duration_string = format!("{:.1}sec", stall_time.as_secs_f32());
531*bb4ee6a4SAndroid Build Coastguard Worker error!(
532*bb4ee6a4SAndroid Build Coastguard Worker "Host stall for {} on VCPU {} exit while handling: {}",
533*bb4ee6a4SAndroid Build Coastguard Worker duration_string, cpu_id, exit_data,
534*bb4ee6a4SAndroid Build Coastguard Worker );
535*bb4ee6a4SAndroid Build Coastguard Worker }
536*bb4ee6a4SAndroid Build Coastguard Worker }
537*bb4ee6a4SAndroid Build Coastguard Worker }
538*bb4ee6a4SAndroid Build Coastguard Worker
setup_vcpu_signal_handler() -> Result<()>539*bb4ee6a4SAndroid Build Coastguard Worker fn setup_vcpu_signal_handler() -> Result<()> {
540*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
541*bb4ee6a4SAndroid Build Coastguard Worker }
542*bb4ee6a4SAndroid Build Coastguard Worker
run_all_vcpus<V: VmArch + 'static, Vcpu: VcpuArch + 'static>( vcpus: Vec<Option<Vcpu>>, vcpu_boxes: Arc<Mutex<Vec<Box<dyn VcpuArch>>>>, guest_os: &RunnableLinuxVm<V, Vcpu>, exit_evt: &Event, vm_evt_wrtube: &SendTube, #[cfg(feature = "stats")] stats: &Option<Arc<Mutex<StatisticsCollector>>>, host_cpu_topology: bool, run_mode_arc: Arc<VcpuRunMode>, tsc_sync_mitigations: TscSyncMitigations, force_calibrated_tsc_leaf: bool, ) -> Result<(Vec<JoinHandle<Result<()>>>, Vec<mpsc::Sender<VcpuControl>>)>543*bb4ee6a4SAndroid Build Coastguard Worker pub fn run_all_vcpus<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
544*bb4ee6a4SAndroid Build Coastguard Worker vcpus: Vec<Option<Vcpu>>,
545*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes: Arc<Mutex<Vec<Box<dyn VcpuArch>>>>,
546*bb4ee6a4SAndroid Build Coastguard Worker guest_os: &RunnableLinuxVm<V, Vcpu>,
547*bb4ee6a4SAndroid Build Coastguard Worker exit_evt: &Event,
548*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube: &SendTube,
549*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] stats: &Option<Arc<Mutex<StatisticsCollector>>>,
550*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology: bool,
551*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc: Arc<VcpuRunMode>,
552*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations: TscSyncMitigations,
553*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf: bool,
554*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(Vec<JoinHandle<Result<()>>>, Vec<mpsc::Sender<VcpuControl>>)> {
555*bb4ee6a4SAndroid Build Coastguard Worker let mut vcpu_threads = Vec::with_capacity(guest_os.vcpu_count + 1);
556*bb4ee6a4SAndroid Build Coastguard Worker let mut vcpu_control_channels = Vec::with_capacity(guest_os.vcpu_count);
557*bb4ee6a4SAndroid Build Coastguard Worker let start_barrier = Arc::new(Barrier::new(guest_os.vcpu_count + 1));
558*bb4ee6a4SAndroid Build Coastguard Worker let enable_vcpu_monitoring = anti_tamper::enable_vcpu_monitoring();
559*bb4ee6a4SAndroid Build Coastguard Worker setup_vcpu_signal_handler()?;
560*bb4ee6a4SAndroid Build Coastguard Worker
561*bb4ee6a4SAndroid Build Coastguard Worker let mut stall_monitor =
562*bb4ee6a4SAndroid Build Coastguard Worker enable_vcpu_monitoring.then(|| VcpuStallMonitor::init(run_mode_arc.clone()));
563*bb4ee6a4SAndroid Build Coastguard Worker for (cpu_id, vcpu) in vcpus.into_iter().enumerate() {
564*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_affinity = match guest_os.vcpu_affinity.clone() {
565*bb4ee6a4SAndroid Build Coastguard Worker Some(VcpuAffinity::Global(v)) => Some(v),
566*bb4ee6a4SAndroid Build Coastguard Worker Some(VcpuAffinity::PerVcpu(mut m)) => Some(m.remove(&cpu_id).unwrap_or_default()),
567*bb4ee6a4SAndroid Build Coastguard Worker None => None,
568*bb4ee6a4SAndroid Build Coastguard Worker };
569*bb4ee6a4SAndroid Build Coastguard Worker
570*bb4ee6a4SAndroid Build Coastguard Worker // TSC sync mitigations may set vcpu affinity and set a TSC offset
571*bb4ee6a4SAndroid Build Coastguard Worker let (vcpu_affinity, tsc_offset): (Option<CpuSet>, Option<u64>) =
572*bb4ee6a4SAndroid Build Coastguard Worker if let Some(mitigation_affinity) = tsc_sync_mitigations.get_vcpu_affinity(cpu_id) {
573*bb4ee6a4SAndroid Build Coastguard Worker if vcpu_affinity.is_none() {
574*bb4ee6a4SAndroid Build Coastguard Worker (
575*bb4ee6a4SAndroid Build Coastguard Worker Some(CpuSet::new(mitigation_affinity)),
576*bb4ee6a4SAndroid Build Coastguard Worker tsc_sync_mitigations.get_vcpu_tsc_offset(cpu_id),
577*bb4ee6a4SAndroid Build Coastguard Worker )
578*bb4ee6a4SAndroid Build Coastguard Worker } else {
579*bb4ee6a4SAndroid Build Coastguard Worker error!(
580*bb4ee6a4SAndroid Build Coastguard Worker "Core affinity {:?} specified via commandline conflicts and overrides \
581*bb4ee6a4SAndroid Build Coastguard Worker affinity needed for TSC sync mitigation: {:?}.",
582*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity, mitigation_affinity
583*bb4ee6a4SAndroid Build Coastguard Worker );
584*bb4ee6a4SAndroid Build Coastguard Worker (vcpu_affinity, None)
585*bb4ee6a4SAndroid Build Coastguard Worker }
586*bb4ee6a4SAndroid Build Coastguard Worker } else {
587*bb4ee6a4SAndroid Build Coastguard Worker (vcpu_affinity, None)
588*bb4ee6a4SAndroid Build Coastguard Worker };
589*bb4ee6a4SAndroid Build Coastguard Worker
590*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_init = &guest_os.vcpu_init[cpu_id];
591*bb4ee6a4SAndroid Build Coastguard Worker // The vcpu_create_barrier allows the main thread to delay the spawning of additional
592*bb4ee6a4SAndroid Build Coastguard Worker // vcpu threads until a single vcpu thread spawned has finished creating it's vcpu.
593*bb4ee6a4SAndroid Build Coastguard Worker // We currently use this to allow creation of 1 vcpu at a time for all hypervisors.
594*bb4ee6a4SAndroid Build Coastguard Worker // There are issues with multiple hypervisors with this approach:
595*bb4ee6a4SAndroid Build Coastguard Worker // - Windows 11 has a regression which causes a BSOD with creation of multiple vcpu
596*bb4ee6a4SAndroid Build Coastguard Worker // in parallel. http://b/229635845 for more details.
597*bb4ee6a4SAndroid Build Coastguard Worker // - GHAXM/HAXM cannot create vcpu0 in parallel with other Vcpus.
598*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_create_barrier = Arc::new(Barrier::new(2));
599*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_run_thread = VcpuRunThread::new(cpu_id, enable_vcpu_monitoring);
600*bb4ee6a4SAndroid Build Coastguard Worker let (vcpu_control_send, vcpu_control_recv) = mpsc::channel();
601*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_channels.push(vcpu_control_send);
602*bb4ee6a4SAndroid Build Coastguard Worker let join_handle = vcpu_run_thread.run(
603*bb4ee6a4SAndroid Build Coastguard Worker vcpu,
604*bb4ee6a4SAndroid Build Coastguard Worker vcpu_init.clone(),
605*bb4ee6a4SAndroid Build Coastguard Worker vcpu_boxes.clone(),
606*bb4ee6a4SAndroid Build Coastguard Worker guest_os
607*bb4ee6a4SAndroid Build Coastguard Worker .vm
608*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
609*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CloneEvent, "failed to clone vm")?,
610*bb4ee6a4SAndroid Build Coastguard Worker guest_os
611*bb4ee6a4SAndroid Build Coastguard Worker .irq_chip
612*bb4ee6a4SAndroid Build Coastguard Worker .try_box_clone()
613*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CloneEvent, "failed to clone event")?,
614*bb4ee6a4SAndroid Build Coastguard Worker guest_os.vcpu_count,
615*bb4ee6a4SAndroid Build Coastguard Worker guest_os.rt_cpus.contains(&cpu_id),
616*bb4ee6a4SAndroid Build Coastguard Worker vcpu_affinity,
617*bb4ee6a4SAndroid Build Coastguard Worker guest_os.delay_rt,
618*bb4ee6a4SAndroid Build Coastguard Worker guest_os.no_smt,
619*bb4ee6a4SAndroid Build Coastguard Worker start_barrier.clone(),
620*bb4ee6a4SAndroid Build Coastguard Worker vcpu_create_barrier.clone(),
621*bb4ee6a4SAndroid Build Coastguard Worker (*guest_os.io_bus).clone(),
622*bb4ee6a4SAndroid Build Coastguard Worker (*guest_os.mmio_bus).clone(),
623*bb4ee6a4SAndroid Build Coastguard Worker vm_evt_wrtube
624*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
625*bb4ee6a4SAndroid Build Coastguard Worker .exit_context(Exit::CloneTube, "failed to clone tube")?,
626*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.clone(),
627*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
628*bb4ee6a4SAndroid Build Coastguard Worker stats.clone(),
629*bb4ee6a4SAndroid Build Coastguard Worker host_cpu_topology,
630*bb4ee6a4SAndroid Build Coastguard Worker tsc_offset,
631*bb4ee6a4SAndroid Build Coastguard Worker force_calibrated_tsc_leaf,
632*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control_recv,
633*bb4ee6a4SAndroid Build Coastguard Worker )?;
634*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref mut monitor) = stall_monitor {
635*bb4ee6a4SAndroid Build Coastguard Worker monitor.add_vcpu_thread(vcpu_run_thread);
636*bb4ee6a4SAndroid Build Coastguard Worker }
637*bb4ee6a4SAndroid Build Coastguard Worker
638*bb4ee6a4SAndroid Build Coastguard Worker // Wait until the vcpu is created before we start a new vcpu thread
639*bb4ee6a4SAndroid Build Coastguard Worker vcpu_create_barrier.wait();
640*bb4ee6a4SAndroid Build Coastguard Worker
641*bb4ee6a4SAndroid Build Coastguard Worker vcpu_threads.push(join_handle);
642*bb4ee6a4SAndroid Build Coastguard Worker }
643*bb4ee6a4SAndroid Build Coastguard Worker if let Some(monitor) = stall_monitor {
644*bb4ee6a4SAndroid Build Coastguard Worker vcpu_threads.push(monitor.run(exit_evt)?);
645*bb4ee6a4SAndroid Build Coastguard Worker }
646*bb4ee6a4SAndroid Build Coastguard Worker // Now wait on the start barrier to start all threads at the same time.
647*bb4ee6a4SAndroid Build Coastguard Worker start_barrier.wait();
648*bb4ee6a4SAndroid Build Coastguard Worker Ok((vcpu_threads, vcpu_control_channels))
649*bb4ee6a4SAndroid Build Coastguard Worker }
650*bb4ee6a4SAndroid Build Coastguard Worker
vcpu_loop<V>( context: &VcpuRunThread, mut vcpu: V, vm: impl VmArch + 'static, irq_chip: Box<dyn IrqChipArch + 'static>, io_bus: Bus, mmio_bus: Bus, run_mode_arc: Arc<VcpuRunMode>, #[cfg(feature = "stats")] stats: Option<Arc<Mutex<StatisticsCollector>>>, #[cfg(target_arch = "x86_64")] cpuid_context: CpuIdContext, vcpu_control: mpsc::Receiver<VcpuControl>, ) -> Result<ExitState> where V: VcpuArch + 'static,651*bb4ee6a4SAndroid Build Coastguard Worker fn vcpu_loop<V>(
652*bb4ee6a4SAndroid Build Coastguard Worker context: &VcpuRunThread,
653*bb4ee6a4SAndroid Build Coastguard Worker mut vcpu: V,
654*bb4ee6a4SAndroid Build Coastguard Worker vm: impl VmArch + 'static,
655*bb4ee6a4SAndroid Build Coastguard Worker irq_chip: Box<dyn IrqChipArch + 'static>,
656*bb4ee6a4SAndroid Build Coastguard Worker io_bus: Bus,
657*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus: Bus,
658*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc: Arc<VcpuRunMode>,
659*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")] stats: Option<Arc<Mutex<StatisticsCollector>>>,
660*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] cpuid_context: CpuIdContext,
661*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control: mpsc::Receiver<VcpuControl>,
662*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<ExitState>
663*bb4ee6a4SAndroid Build Coastguard Worker where
664*bb4ee6a4SAndroid Build Coastguard Worker V: VcpuArch + 'static,
665*bb4ee6a4SAndroid Build Coastguard Worker {
666*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
667*bb4ee6a4SAndroid Build Coastguard Worker let mut exit_stats = VmExitStatistics::new();
668*bb4ee6a4SAndroid Build Coastguard Worker
669*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
670*bb4ee6a4SAndroid Build Coastguard Worker {
671*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus.stats.lock().set_enabled(stats.is_some());
672*bb4ee6a4SAndroid Build Coastguard Worker io_bus.stats.lock().set_enabled(stats.is_some());
673*bb4ee6a4SAndroid Build Coastguard Worker exit_stats.set_enabled(stats.is_some());
674*bb4ee6a4SAndroid Build Coastguard Worker }
675*bb4ee6a4SAndroid Build Coastguard Worker
676*bb4ee6a4SAndroid Build Coastguard Worker let mut save_tsc_offset = true;
677*bb4ee6a4SAndroid Build Coastguard Worker
678*bb4ee6a4SAndroid Build Coastguard Worker loop {
679*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "vcpu loop");
680*bb4ee6a4SAndroid Build Coastguard Worker let mut check_vm_shutdown = run_mode_arc.get_mode() != VmRunMode::Running;
681*bb4ee6a4SAndroid Build Coastguard Worker
682*bb4ee6a4SAndroid Build Coastguard Worker match irq_chip.wait_until_runnable(&vcpu).with_exit_context(
683*bb4ee6a4SAndroid Build Coastguard Worker Exit::WaitUntilRunnable,
684*bb4ee6a4SAndroid Build Coastguard Worker || {
685*bb4ee6a4SAndroid Build Coastguard Worker format!(
686*bb4ee6a4SAndroid Build Coastguard Worker "error waiting for vcpu {} to become runnable",
687*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id
688*bb4ee6a4SAndroid Build Coastguard Worker )
689*bb4ee6a4SAndroid Build Coastguard Worker },
690*bb4ee6a4SAndroid Build Coastguard Worker )? {
691*bb4ee6a4SAndroid Build Coastguard Worker VcpuRunState::Runnable => {}
692*bb4ee6a4SAndroid Build Coastguard Worker VcpuRunState::Interrupted => check_vm_shutdown = true,
693*bb4ee6a4SAndroid Build Coastguard Worker }
694*bb4ee6a4SAndroid Build Coastguard Worker
695*bb4ee6a4SAndroid Build Coastguard Worker if !check_vm_shutdown {
696*bb4ee6a4SAndroid Build Coastguard Worker let exit = {
697*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "vcpu::run");
698*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref monitoring_metadata) = context.monitoring_metadata {
699*bb4ee6a4SAndroid Build Coastguard Worker monitoring_metadata.last_run_time.store(
700*bb4ee6a4SAndroid Build Coastguard Worker // Safe conversion because millis will always be < u32::MAX
701*bb4ee6a4SAndroid Build Coastguard Worker monitoring_metadata
702*bb4ee6a4SAndroid Build Coastguard Worker .start_instant
703*bb4ee6a4SAndroid Build Coastguard Worker .elapsed()
704*bb4ee6a4SAndroid Build Coastguard Worker .as_millis()
705*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
706*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(),
707*bb4ee6a4SAndroid Build Coastguard Worker Ordering::SeqCst,
708*bb4ee6a4SAndroid Build Coastguard Worker );
709*bb4ee6a4SAndroid Build Coastguard Worker }
710*bb4ee6a4SAndroid Build Coastguard Worker vcpu.run()
711*bb4ee6a4SAndroid Build Coastguard Worker };
712*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref monitoring_metadata) = context.monitoring_metadata {
713*bb4ee6a4SAndroid Build Coastguard Worker *monitoring_metadata.last_exit_snapshot.lock() = Some(VcpuExitData {
714*bb4ee6a4SAndroid Build Coastguard Worker exit_time: monitoring_metadata.start_instant.elapsed(),
715*bb4ee6a4SAndroid Build Coastguard Worker exit_result: exit,
716*bb4ee6a4SAndroid Build Coastguard Worker });
717*bb4ee6a4SAndroid Build Coastguard Worker }
718*bb4ee6a4SAndroid Build Coastguard Worker
719*bb4ee6a4SAndroid Build Coastguard Worker // save the tsc offset if we need to
720*bb4ee6a4SAndroid Build Coastguard Worker if save_tsc_offset {
721*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(offset) = vcpu.get_tsc_offset() {
722*bb4ee6a4SAndroid Build Coastguard Worker save_vcpu_tsc_offset(offset, context.cpu_id);
723*bb4ee6a4SAndroid Build Coastguard Worker } else {
724*bb4ee6a4SAndroid Build Coastguard Worker error!("Unable to determine TSC offset");
725*bb4ee6a4SAndroid Build Coastguard Worker }
726*bb4ee6a4SAndroid Build Coastguard Worker save_tsc_offset = false;
727*bb4ee6a4SAndroid Build Coastguard Worker }
728*bb4ee6a4SAndroid Build Coastguard Worker
729*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
730*bb4ee6a4SAndroid Build Coastguard Worker let start = exit_stats.start_stat();
731*bb4ee6a4SAndroid Build Coastguard Worker
732*bb4ee6a4SAndroid Build Coastguard Worker match exit {
733*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Io) => {
734*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Io");
735*bb4ee6a4SAndroid Build Coastguard Worker vcpu.handle_io(&mut |IoParams { address, operation}| {
736*bb4ee6a4SAndroid Build Coastguard Worker match operation {
737*bb4ee6a4SAndroid Build Coastguard Worker IoOperation::Read(data) => {
738*bb4ee6a4SAndroid Build Coastguard Worker io_bus.read(address, data);
739*bb4ee6a4SAndroid Build Coastguard Worker }
740*bb4ee6a4SAndroid Build Coastguard Worker IoOperation::Write(data) => {
741*bb4ee6a4SAndroid Build Coastguard Worker vm.handle_io_events(IoEventAddress::Pio(address), data)
742*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| error!(
743*bb4ee6a4SAndroid Build Coastguard Worker "failed to handle ioevent for pio write to {} on vcpu {}: {}",
744*bb4ee6a4SAndroid Build Coastguard Worker address, context.cpu_id, e
745*bb4ee6a4SAndroid Build Coastguard Worker ));
746*bb4ee6a4SAndroid Build Coastguard Worker io_bus.write(address, data);
747*bb4ee6a4SAndroid Build Coastguard Worker }
748*bb4ee6a4SAndroid Build Coastguard Worker }
749*bb4ee6a4SAndroid Build Coastguard Worker }).unwrap_or_else(|e| error!("failed to handle io: {}", e));
750*bb4ee6a4SAndroid Build Coastguard Worker }
751*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Mmio) => {
752*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Mmio");
753*bb4ee6a4SAndroid Build Coastguard Worker vcpu.handle_mmio(&mut |IoParams { address, operation }| {
754*bb4ee6a4SAndroid Build Coastguard Worker match operation {
755*bb4ee6a4SAndroid Build Coastguard Worker IoOperation::Read(data) => {
756*bb4ee6a4SAndroid Build Coastguard Worker if !mmio_bus.read(address, data) {
757*bb4ee6a4SAndroid Build Coastguard Worker info!(
758*bb4ee6a4SAndroid Build Coastguard Worker "mmio read failed: {:x}; trying memory read..",
759*bb4ee6a4SAndroid Build Coastguard Worker address
760*bb4ee6a4SAndroid Build Coastguard Worker );
761*bb4ee6a4SAndroid Build Coastguard Worker vm.get_memory()
762*bb4ee6a4SAndroid Build Coastguard Worker .read_exact_at_addr(
763*bb4ee6a4SAndroid Build Coastguard Worker data,
764*bb4ee6a4SAndroid Build Coastguard Worker vm_memory::GuestAddress(address),
765*bb4ee6a4SAndroid Build Coastguard Worker )
766*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| {
767*bb4ee6a4SAndroid Build Coastguard Worker error!(
768*bb4ee6a4SAndroid Build Coastguard Worker "guest memory read failed at {:x}: {}",
769*bb4ee6a4SAndroid Build Coastguard Worker address, e
770*bb4ee6a4SAndroid Build Coastguard Worker )
771*bb4ee6a4SAndroid Build Coastguard Worker });
772*bb4ee6a4SAndroid Build Coastguard Worker }
773*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
774*bb4ee6a4SAndroid Build Coastguard Worker }
775*bb4ee6a4SAndroid Build Coastguard Worker IoOperation::Write(data) => {
776*bb4ee6a4SAndroid Build Coastguard Worker vm.handle_io_events(IoEventAddress::Mmio(address), data)
777*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| error!(
778*bb4ee6a4SAndroid Build Coastguard Worker "failed to handle ioevent for mmio write to {} on vcpu {}: {}",
779*bb4ee6a4SAndroid Build Coastguard Worker address, context.cpu_id, e
780*bb4ee6a4SAndroid Build Coastguard Worker ));
781*bb4ee6a4SAndroid Build Coastguard Worker if !mmio_bus.write(address, data) {
782*bb4ee6a4SAndroid Build Coastguard Worker info!(
783*bb4ee6a4SAndroid Build Coastguard Worker "mmio write failed: {:x}; trying memory write..",
784*bb4ee6a4SAndroid Build Coastguard Worker address
785*bb4ee6a4SAndroid Build Coastguard Worker );
786*bb4ee6a4SAndroid Build Coastguard Worker vm.get_memory()
787*bb4ee6a4SAndroid Build Coastguard Worker .write_all_at_addr(data, vm_memory::GuestAddress(address))
788*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| error!(
789*bb4ee6a4SAndroid Build Coastguard Worker "guest memory write failed at {:x}: {}",
790*bb4ee6a4SAndroid Build Coastguard Worker address, e
791*bb4ee6a4SAndroid Build Coastguard Worker ));
792*bb4ee6a4SAndroid Build Coastguard Worker }
793*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
794*bb4ee6a4SAndroid Build Coastguard Worker }
795*bb4ee6a4SAndroid Build Coastguard Worker }
796*bb4ee6a4SAndroid Build Coastguard Worker }).unwrap_or_else(|e| error!("failed to handle mmio: {}", e));
797*bb4ee6a4SAndroid Build Coastguard Worker }
798*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::IoapicEoi { vector }) => {
799*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::IoapicEoi");
800*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.broadcast_eoi(vector).unwrap_or_else(|e| {
801*bb4ee6a4SAndroid Build Coastguard Worker error!(
802*bb4ee6a4SAndroid Build Coastguard Worker "failed to broadcast eoi {} on vcpu {}: {}",
803*bb4ee6a4SAndroid Build Coastguard Worker vector, context.cpu_id, e
804*bb4ee6a4SAndroid Build Coastguard Worker )
805*bb4ee6a4SAndroid Build Coastguard Worker });
806*bb4ee6a4SAndroid Build Coastguard Worker }
807*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::IrqWindowOpen) => {
808*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::IrqWindowOpen");
809*bb4ee6a4SAndroid Build Coastguard Worker }
810*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Hlt) => irq_chip.halted(context.cpu_id),
811*bb4ee6a4SAndroid Build Coastguard Worker
812*bb4ee6a4SAndroid Build Coastguard Worker // VcpuExit::Shutdown is always an error on Windows. HAXM exits with
813*bb4ee6a4SAndroid Build Coastguard Worker // Shutdown only for triple faults and other vcpu panics. WHPX never exits
814*bb4ee6a4SAndroid Build Coastguard Worker // with Shutdown. Normal reboots and shutdowns, like window close, use
815*bb4ee6a4SAndroid Build Coastguard Worker // the vm event tube and VmRunMode::Exiting instead of VcpuExit::Shutdown.
816*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Shutdown(reason)) => {
817*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = reason {
818*bb4ee6a4SAndroid Build Coastguard Worker metrics::log_descriptor(
819*bb4ee6a4SAndroid Build Coastguard Worker MetricEventType::VcpuShutdownError,
820*bb4ee6a4SAndroid Build Coastguard Worker e.get_raw_error_code() as i64,
821*bb4ee6a4SAndroid Build Coastguard Worker );
822*bb4ee6a4SAndroid Build Coastguard Worker }
823*bb4ee6a4SAndroid Build Coastguard Worker bail_exit_code!(Exit::VcpuShutdown, "vcpu shutdown (reason: {:?})", reason)
824*bb4ee6a4SAndroid Build Coastguard Worker }
825*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::FailEntry {
826*bb4ee6a4SAndroid Build Coastguard Worker hardware_entry_failure_reason,
827*bb4ee6a4SAndroid Build Coastguard Worker }) => bail_exit_code!(
828*bb4ee6a4SAndroid Build Coastguard Worker Exit::VcpuFailEntry,
829*bb4ee6a4SAndroid Build Coastguard Worker "vcpu hw run failure: {:#x}",
830*bb4ee6a4SAndroid Build Coastguard Worker hardware_entry_failure_reason,
831*bb4ee6a4SAndroid Build Coastguard Worker ),
832*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::SystemEventShutdown) => {
833*bb4ee6a4SAndroid Build Coastguard Worker bail_exit_code!(Exit::VcpuSystemEvent, "vcpu SystemEventShutdown")
834*bb4ee6a4SAndroid Build Coastguard Worker }
835*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::SystemEventReset) => {
836*bb4ee6a4SAndroid Build Coastguard Worker bail_exit_code!(Exit::VcpuSystemEvent, "vcpu SystemEventReset")
837*bb4ee6a4SAndroid Build Coastguard Worker }
838*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::SystemEventCrash) => {
839*bb4ee6a4SAndroid Build Coastguard Worker bail_exit_code!(Exit::VcpuSystemEvent, "vcpu SystemEventCrash")
840*bb4ee6a4SAndroid Build Coastguard Worker }
841*bb4ee6a4SAndroid Build Coastguard Worker
842*bb4ee6a4SAndroid Build Coastguard Worker // When we're shutting down (e.g., emulator window gets closed), GVM vmexits
843*bb4ee6a4SAndroid Build Coastguard Worker // with KVM_EXIT_INTR, which vcpu.run maps to VcpuExit::Intr. But KVM_EXIT_INTR
844*bb4ee6a4SAndroid Build Coastguard Worker // can happen during normal operation too, when GVM's timer finds requests
845*bb4ee6a4SAndroid Build Coastguard Worker // pending from the host. So we set check_vm_shutdown, then below check the
846*bb4ee6a4SAndroid Build Coastguard Worker // VmRunMode state to see if we should exit the run loop.
847*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Intr) => {
848*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Intr");
849*bb4ee6a4SAndroid Build Coastguard Worker check_vm_shutdown = true
850*bb4ee6a4SAndroid Build Coastguard Worker }
851*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Canceled) => {
852*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Canceled");
853*bb4ee6a4SAndroid Build Coastguard Worker check_vm_shutdown = true
854*bb4ee6a4SAndroid Build Coastguard Worker }
855*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
856*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::Cpuid { mut entry }) => {
857*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Cpuid");
858*bb4ee6a4SAndroid Build Coastguard Worker // adjust the results based on crosvm logic
859*bb4ee6a4SAndroid Build Coastguard Worker adjust_cpuid(&mut entry, &cpuid_context);
860*bb4ee6a4SAndroid Build Coastguard Worker
861*bb4ee6a4SAndroid Build Coastguard Worker // let the vcpu finish handling the exit
862*bb4ee6a4SAndroid Build Coastguard Worker vcpu.handle_cpuid(&entry).unwrap_or_else(|e| {
863*bb4ee6a4SAndroid Build Coastguard Worker error!(
864*bb4ee6a4SAndroid Build Coastguard Worker "failed to handle setting cpuid results on cpu {}: {}",
865*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id, e
866*bb4ee6a4SAndroid Build Coastguard Worker )
867*bb4ee6a4SAndroid Build Coastguard Worker });
868*bb4ee6a4SAndroid Build Coastguard Worker }
869*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
870*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::MsrAccess) => {
871*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::MsrAccess");
872*bb4ee6a4SAndroid Build Coastguard Worker } // MsrAccess handled by hypervisor impl
873*bb4ee6a4SAndroid Build Coastguard Worker Ok(r) => {
874*bb4ee6a4SAndroid Build Coastguard Worker let _trace_event = trace_event!(crosvm, "VcpuExit::Unexpected");
875*bb4ee6a4SAndroid Build Coastguard Worker error!("unexpected vcpu.run return value: {:?}", r);
876*bb4ee6a4SAndroid Build Coastguard Worker check_vm_shutdown = true;
877*bb4ee6a4SAndroid Build Coastguard Worker }
878*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => match e.errno() {
879*bb4ee6a4SAndroid Build Coastguard Worker ERROR_RETRY_I32 => {}
880*bb4ee6a4SAndroid Build Coastguard Worker _ => {
881*bb4ee6a4SAndroid Build Coastguard Worker run_mode_arc.set_and_notify(VmRunMode::Exiting);
882*bb4ee6a4SAndroid Build Coastguard Worker Err(e).exit_context(Exit::VcpuRunError, "vcpu run error")?;
883*bb4ee6a4SAndroid Build Coastguard Worker }
884*bb4ee6a4SAndroid Build Coastguard Worker },
885*bb4ee6a4SAndroid Build Coastguard Worker }
886*bb4ee6a4SAndroid Build Coastguard Worker
887*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
888*bb4ee6a4SAndroid Build Coastguard Worker exit_stats.end_stat(&exit, start);
889*bb4ee6a4SAndroid Build Coastguard Worker }
890*bb4ee6a4SAndroid Build Coastguard Worker
891*bb4ee6a4SAndroid Build Coastguard Worker if check_vm_shutdown {
892*bb4ee6a4SAndroid Build Coastguard Worker let mut run_mode_lock = run_mode_arc.mtx.lock();
893*bb4ee6a4SAndroid Build Coastguard Worker loop {
894*bb4ee6a4SAndroid Build Coastguard Worker match *run_mode_lock {
895*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Running => {
896*bb4ee6a4SAndroid Build Coastguard Worker process_vcpu_control_messages(&mut vcpu, *run_mode_lock, &vcpu_control);
897*bb4ee6a4SAndroid Build Coastguard Worker break;
898*bb4ee6a4SAndroid Build Coastguard Worker }
899*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Suspending => {
900*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = vcpu.on_suspend() {
901*bb4ee6a4SAndroid Build Coastguard Worker error!(
902*bb4ee6a4SAndroid Build Coastguard Worker "failed to signal to hypervisor that vcpu {} is being suspended: {}",
903*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id, e
904*bb4ee6a4SAndroid Build Coastguard Worker );
905*bb4ee6a4SAndroid Build Coastguard Worker }
906*bb4ee6a4SAndroid Build Coastguard Worker }
907*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Breakpoint => {}
908*bb4ee6a4SAndroid Build Coastguard Worker VmRunMode::Exiting => {
909*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
910*bb4ee6a4SAndroid Build Coastguard Worker if let Some(stats) = stats {
911*bb4ee6a4SAndroid Build Coastguard Worker let mut collector = stats.lock();
912*bb4ee6a4SAndroid Build Coastguard Worker collector.pio_bus_stats.push(io_bus.stats);
913*bb4ee6a4SAndroid Build Coastguard Worker collector.mmio_bus_stats.push(mmio_bus.stats);
914*bb4ee6a4SAndroid Build Coastguard Worker collector.vm_exit_stats.push(exit_stats);
915*bb4ee6a4SAndroid Build Coastguard Worker }
916*bb4ee6a4SAndroid Build Coastguard Worker return Ok(ExitState::Stop);
917*bb4ee6a4SAndroid Build Coastguard Worker }
918*bb4ee6a4SAndroid Build Coastguard Worker }
919*bb4ee6a4SAndroid Build Coastguard Worker
920*bb4ee6a4SAndroid Build Coastguard Worker // For non running modes, we don't want to process messages until we've completed
921*bb4ee6a4SAndroid Build Coastguard Worker // *all* work for any VmRunMode transition. This is because one control message
922*bb4ee6a4SAndroid Build Coastguard Worker // asks us to inform the requestor of our current state. We want to make sure our
923*bb4ee6a4SAndroid Build Coastguard Worker // our state has completely transitioned before we respond to the requestor. If
924*bb4ee6a4SAndroid Build Coastguard Worker // we do this elsewhere, we might respond while in a partial state which could
925*bb4ee6a4SAndroid Build Coastguard Worker // break features like snapshotting (e.g. by introducing a race condition).
926*bb4ee6a4SAndroid Build Coastguard Worker process_vcpu_control_messages(&mut vcpu, *run_mode_lock, &vcpu_control);
927*bb4ee6a4SAndroid Build Coastguard Worker
928*bb4ee6a4SAndroid Build Coastguard Worker // Give ownership of our exclusive lock to the condition variable that
929*bb4ee6a4SAndroid Build Coastguard Worker // will block. When the condition variable is notified, `wait` will
930*bb4ee6a4SAndroid Build Coastguard Worker // unblock and return a new exclusive lock.
931*bb4ee6a4SAndroid Build Coastguard Worker run_mode_lock = run_mode_arc.cvar.wait(run_mode_lock);
932*bb4ee6a4SAndroid Build Coastguard Worker }
933*bb4ee6a4SAndroid Build Coastguard Worker }
934*bb4ee6a4SAndroid Build Coastguard Worker
935*bb4ee6a4SAndroid Build Coastguard Worker irq_chip.inject_interrupts(&vcpu).unwrap_or_else(|e| {
936*bb4ee6a4SAndroid Build Coastguard Worker error!(
937*bb4ee6a4SAndroid Build Coastguard Worker "failed to inject interrupts for vcpu {}: {}",
938*bb4ee6a4SAndroid Build Coastguard Worker context.cpu_id, e
939*bb4ee6a4SAndroid Build Coastguard Worker )
940*bb4ee6a4SAndroid Build Coastguard Worker });
941*bb4ee6a4SAndroid Build Coastguard Worker }
942*bb4ee6a4SAndroid Build Coastguard Worker }
943*bb4ee6a4SAndroid Build Coastguard Worker
process_vcpu_control_messages<V>( vcpu: &mut V, run_mode: VmRunMode, vcpu_control: &mpsc::Receiver<VcpuControl>, ) where V: VcpuArch + 'static,944*bb4ee6a4SAndroid Build Coastguard Worker fn process_vcpu_control_messages<V>(
945*bb4ee6a4SAndroid Build Coastguard Worker vcpu: &mut V,
946*bb4ee6a4SAndroid Build Coastguard Worker run_mode: VmRunMode,
947*bb4ee6a4SAndroid Build Coastguard Worker vcpu_control: &mpsc::Receiver<VcpuControl>,
948*bb4ee6a4SAndroid Build Coastguard Worker ) where
949*bb4ee6a4SAndroid Build Coastguard Worker V: VcpuArch + 'static,
950*bb4ee6a4SAndroid Build Coastguard Worker {
951*bb4ee6a4SAndroid Build Coastguard Worker let control_messages: Vec<VcpuControl> = vcpu_control.try_iter().collect();
952*bb4ee6a4SAndroid Build Coastguard Worker
953*bb4ee6a4SAndroid Build Coastguard Worker for msg in control_messages {
954*bb4ee6a4SAndroid Build Coastguard Worker match msg {
955*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::RunState(new_mode) => {
956*bb4ee6a4SAndroid Build Coastguard Worker panic!("VCPUs do not handle RunState messages on Windows")
957*bb4ee6a4SAndroid Build Coastguard Worker }
958*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gdb")]
959*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::Debug(d) => {
960*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("Windows VCPUs do not support debug yet.");
961*bb4ee6a4SAndroid Build Coastguard Worker }
962*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::MakeRT => {
963*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("Windows VCPUs do not support on demand RT.");
964*bb4ee6a4SAndroid Build Coastguard Worker }
965*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::GetStates(response_chan) => {
966*bb4ee6a4SAndroid Build Coastguard Worker // Wondering why we need this given that the state value is already in an Arc?
967*bb4ee6a4SAndroid Build Coastguard Worker //
968*bb4ee6a4SAndroid Build Coastguard Worker // The control loop generally sets the run mode directly via the Arc; however,
969*bb4ee6a4SAndroid Build Coastguard Worker // it has no way of knowing *when* the VCPU threads have actually acknowledged
970*bb4ee6a4SAndroid Build Coastguard Worker // the new value. By returning the value in here, we prove the the control loop
971*bb4ee6a4SAndroid Build Coastguard Worker // we have accepted the new value and are done with our state change.
972*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = response_chan.send(run_mode) {
973*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to send GetState: {}", e);
974*bb4ee6a4SAndroid Build Coastguard Worker };
975*bb4ee6a4SAndroid Build Coastguard Worker }
976*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::Snapshot(snapshot_writer, response_chan) => {
977*bb4ee6a4SAndroid Build Coastguard Worker let resp = vcpu
978*bb4ee6a4SAndroid Build Coastguard Worker .snapshot()
979*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|s| snapshot_writer.write_fragment(&format!("vcpu{}", vcpu.id()), &s))
980*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| format!("Failed to snapshot Vcpu #{}", vcpu.id()));
981*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = response_chan.send(resp) {
982*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to send snapshot response: {}", e);
983*bb4ee6a4SAndroid Build Coastguard Worker }
984*bb4ee6a4SAndroid Build Coastguard Worker }
985*bb4ee6a4SAndroid Build Coastguard Worker VcpuControl::Restore(req) => {
986*bb4ee6a4SAndroid Build Coastguard Worker let resp = req
987*bb4ee6a4SAndroid Build Coastguard Worker .snapshot_reader
988*bb4ee6a4SAndroid Build Coastguard Worker .read_fragment(&format!("vcpu{}", vcpu.id()))
989*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|s| vcpu.restore(&s, req.host_tsc_reference_moment))
990*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| format!("Failed to restore Vcpu #{}", vcpu.id()));
991*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = req.result_sender.send(resp) {
992*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to send restore response: {}", e);
993*bb4ee6a4SAndroid Build Coastguard Worker }
994*bb4ee6a4SAndroid Build Coastguard Worker }
995*bb4ee6a4SAndroid Build Coastguard Worker }
996*bb4ee6a4SAndroid Build Coastguard Worker }
997*bb4ee6a4SAndroid Build Coastguard Worker }
998*bb4ee6a4SAndroid Build Coastguard Worker
999*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1000*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1001*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
1002*bb4ee6a4SAndroid Build Coastguard Worker
1003*bb4ee6a4SAndroid Build Coastguard Worker struct SetupData {
1004*bb4ee6a4SAndroid Build Coastguard Worker pub monitor: VcpuStallMonitor,
1005*bb4ee6a4SAndroid Build Coastguard Worker pub exit_evt: Event,
1006*bb4ee6a4SAndroid Build Coastguard Worker }
1007*bb4ee6a4SAndroid Build Coastguard Worker
set_up_stall_monitor(vcpu_count: usize) -> Result<SetupData>1008*bb4ee6a4SAndroid Build Coastguard Worker fn set_up_stall_monitor(vcpu_count: usize) -> Result<SetupData> {
1009*bb4ee6a4SAndroid Build Coastguard Worker let run_mode = Arc::new(VcpuRunMode::default());
1010*bb4ee6a4SAndroid Build Coastguard Worker let mut monitor = VcpuStallMonitor::init(run_mode);
1011*bb4ee6a4SAndroid Build Coastguard Worker
1012*bb4ee6a4SAndroid Build Coastguard Worker for id in 0..vcpu_count {
1013*bb4ee6a4SAndroid Build Coastguard Worker let new_vcpu = VcpuRunThread::new(id, true /* enable_vcpu_monitoring */);
1014*bb4ee6a4SAndroid Build Coastguard Worker monitor.add_vcpu_thread(new_vcpu);
1015*bb4ee6a4SAndroid Build Coastguard Worker }
1016*bb4ee6a4SAndroid Build Coastguard Worker
1017*bb4ee6a4SAndroid Build Coastguard Worker Ok(SetupData {
1018*bb4ee6a4SAndroid Build Coastguard Worker monitor,
1019*bb4ee6a4SAndroid Build Coastguard Worker exit_evt: Event::new().expect("Failed to create event"),
1020*bb4ee6a4SAndroid Build Coastguard Worker })
1021*bb4ee6a4SAndroid Build Coastguard Worker }
1022*bb4ee6a4SAndroid Build Coastguard Worker
1023*bb4ee6a4SAndroid Build Coastguard Worker #[test]
stall_monitor_closes_on_exit_evt() -> Result<()>1024*bb4ee6a4SAndroid Build Coastguard Worker fn stall_monitor_closes_on_exit_evt() -> Result<()> {
1025*bb4ee6a4SAndroid Build Coastguard Worker let SetupData { monitor, exit_evt } = set_up_stall_monitor(1)?;
1026*bb4ee6a4SAndroid Build Coastguard Worker
1027*bb4ee6a4SAndroid Build Coastguard Worker exit_evt.signal()?;
1028*bb4ee6a4SAndroid Build Coastguard Worker let _ = monitor
1029*bb4ee6a4SAndroid Build Coastguard Worker .run(&exit_evt)?
1030*bb4ee6a4SAndroid Build Coastguard Worker .join()
1031*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|e| panic!("Thread join failed: {:?}", e));
1032*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1033*bb4ee6a4SAndroid Build Coastguard Worker }
1034*bb4ee6a4SAndroid Build Coastguard Worker }
1035