xref: /aosp_15_r20/external/crosvm/devices/src/irqchip/userspace.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::iter;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker cfg_if::cfg_if! {
13*bb4ee6a4SAndroid Build Coastguard Worker     if #[cfg(test)] {
14*bb4ee6a4SAndroid Build Coastguard Worker         use base::{FakeClock as Clock, FakeTimer as Timer};
15*bb4ee6a4SAndroid Build Coastguard Worker     } else {
16*bb4ee6a4SAndroid Build Coastguard Worker         use base::{Clock, Timer};
17*bb4ee6a4SAndroid Build Coastguard Worker     }
18*bb4ee6a4SAndroid Build Coastguard Worker }
19*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::Descriptor;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
30*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
31*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
32*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::DeliveryMode;
33*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoapicState;
34*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute;
35*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSource;
36*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSourceChip;
37*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::LapicState;
38*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MPState;
39*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MsiAddressMessage;
40*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MsiDataMessage;
41*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicSelect;
42*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicState;
43*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PitState;
44*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vcpu;
45*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuX86_64;
46*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
47*bb4ee6a4SAndroid Build Coastguard Worker use sync::Condvar;
48*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::BusDeviceSync;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Apic;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::ApicBusMsg;
53*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::DelayedIoApicIrqEvents;
54*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Interrupt;
55*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::InterruptData;
56*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::InterruptDestination;
57*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Ioapic;
58*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IrqEvent;
59*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IrqEventIndex;
60*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Pic;
61*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Routes;
62*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::VcpuRunState;
63*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::APIC_BASE_ADDRESS;
64*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::APIC_MEM_LENGTH_BYTES;
65*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IOAPIC_BASE_ADDRESS;
66*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IOAPIC_MEM_LENGTH_BYTES;
67*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
68*bb4ee6a4SAndroid Build Coastguard Worker use crate::Bus;
69*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
70*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
71*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
72*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip;
73*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipCap;
74*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipX86_64;
75*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEdgeEvent;
76*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventSource;
77*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
78*bb4ee6a4SAndroid Build Coastguard Worker use crate::Pit;
79*bb4ee6a4SAndroid Build Coastguard Worker use crate::PitError;
80*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker /// PIT channel 0 timer is connected to IRQ 0
83*bb4ee6a4SAndroid Build Coastguard Worker const PIT_CHANNEL0_IRQ: u32 = 0;
84*bb4ee6a4SAndroid Build Coastguard Worker /// CR0 extension type bit
85*bb4ee6a4SAndroid Build Coastguard Worker const X86_CR0_ET: u64 = 0x00000010;
86*bb4ee6a4SAndroid Build Coastguard Worker /// CR0 not write through bit
87*bb4ee6a4SAndroid Build Coastguard Worker const X86_CR0_NW: u64 = 0x20000000;
88*bb4ee6a4SAndroid Build Coastguard Worker /// CR0 cache disable bit
89*bb4ee6a4SAndroid Build Coastguard Worker const X86_CR0_CD: u64 = 0x40000000;
90*bb4ee6a4SAndroid Build Coastguard Worker /// Default power on state of CR0 register, according to the Intel manual.
91*bb4ee6a4SAndroid Build Coastguard Worker const X86_CR0_INIT: u64 = X86_CR0_ET | X86_CR0_NW | X86_CR0_CD;
92*bb4ee6a4SAndroid Build Coastguard Worker 
93*bb4ee6a4SAndroid Build Coastguard Worker /// An `IrqChip` with all interrupt devices emulated in userspace.  `UserspaceIrqChip` works with
94*bb4ee6a4SAndroid Build Coastguard Worker /// any hypervisor, but only supports x86.
95*bb4ee6a4SAndroid Build Coastguard Worker pub struct UserspaceIrqChip<V: VcpuX86_64> {
96*bb4ee6a4SAndroid Build Coastguard Worker     pub vcpus: Arc<Mutex<Vec<Option<V>>>>,
97*bb4ee6a4SAndroid Build Coastguard Worker     routes: Arc<Mutex<Routes>>,
98*bb4ee6a4SAndroid Build Coastguard Worker     pit: Arc<Mutex<Pit>>,
99*bb4ee6a4SAndroid Build Coastguard Worker     pic: Arc<Mutex<Pic>>,
100*bb4ee6a4SAndroid Build Coastguard Worker     ioapic: Arc<Mutex<Ioapic>>,
101*bb4ee6a4SAndroid Build Coastguard Worker     ioapic_pins: usize,
102*bb4ee6a4SAndroid Build Coastguard Worker     pub apics: Vec<Arc<Mutex<Apic>>>,
103*bb4ee6a4SAndroid Build Coastguard Worker     // Condition variables used by wait_until_runnable.
104*bb4ee6a4SAndroid Build Coastguard Worker     waiters: Vec<Arc<Waiter>>,
105*bb4ee6a4SAndroid Build Coastguard Worker     // Raw descriptors of the apic Timers.
106*bb4ee6a4SAndroid Build Coastguard Worker     timer_descriptors: Vec<Descriptor>,
107*bb4ee6a4SAndroid Build Coastguard Worker     /// Delayed ioapic irq object, that contains the delayed events because the ioapic was locked
108*bb4ee6a4SAndroid Build Coastguard Worker     /// when service_irq was called on the irqchip. This prevents deadlocks when a Vcpu thread has
109*bb4ee6a4SAndroid Build Coastguard Worker     /// locked the ioapic and the ioapic sends a AddMsiRoute signal to the main thread (which
110*bb4ee6a4SAndroid Build Coastguard Worker     /// itself may be busy trying to call service_irq).
111*bb4ee6a4SAndroid Build Coastguard Worker     ///
112*bb4ee6a4SAndroid Build Coastguard Worker     /// ## Note:
113*bb4ee6a4SAndroid Build Coastguard Worker     /// This lock may be locked by itself to access the `DelayedIoApicIrqEvents`. If accessed in
114*bb4ee6a4SAndroid Build Coastguard Worker     /// conjunction with the `irq_events` field, that lock should be taken first to prevent
115*bb4ee6a4SAndroid Build Coastguard Worker     /// deadlocks stemming from lock-ordering issues.
116*bb4ee6a4SAndroid Build Coastguard Worker     delayed_ioapic_irq_events: Arc<Mutex<DelayedIoApicIrqEvents>>,
117*bb4ee6a4SAndroid Build Coastguard Worker     // Array of Events that devices will use to assert ioapic pins.
118*bb4ee6a4SAndroid Build Coastguard Worker     irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>,
119*bb4ee6a4SAndroid Build Coastguard Worker     dropper: Arc<Mutex<Dropper>>,
120*bb4ee6a4SAndroid Build Coastguard Worker     activated: bool,
121*bb4ee6a4SAndroid Build Coastguard Worker }
122*bb4ee6a4SAndroid Build Coastguard Worker 
123*bb4ee6a4SAndroid Build Coastguard Worker /// Helper that implements `Drop` on behalf of `UserspaceIrqChip`.  The many cloned copies of an irq
124*bb4ee6a4SAndroid Build Coastguard Worker /// chip share a single arc'ed `Dropper`, which only runs its drop when the last irq chip copy is
125*bb4ee6a4SAndroid Build Coastguard Worker /// dropped.
126*bb4ee6a4SAndroid Build Coastguard Worker struct Dropper {
127*bb4ee6a4SAndroid Build Coastguard Worker     /// Worker threads that deliver timer events to the APICs.
128*bb4ee6a4SAndroid Build Coastguard Worker     workers: Vec<WorkerThread<TimerWorkerResult<()>>>,
129*bb4ee6a4SAndroid Build Coastguard Worker }
130*bb4ee6a4SAndroid Build Coastguard Worker 
131*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> UserspaceIrqChip<V> {
132*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a new `UserspaceIrqChip`.
new(num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize>) -> Result<Self>133*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize>) -> Result<Self> {
134*bb4ee6a4SAndroid Build Coastguard Worker         let clock = Arc::new(Mutex::new(Clock::new()));
135*bb4ee6a4SAndroid Build Coastguard Worker         Self::new_with_clock(num_vcpus, irq_tube, ioapic_pins, clock)
136*bb4ee6a4SAndroid Build Coastguard Worker     }
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a new `UserspaceIrqChip`, with a clock.  Used for testing.
new_with_clock( num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize>, clock: Arc<Mutex<Clock>>, ) -> Result<Self>139*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_with_clock(
140*bb4ee6a4SAndroid Build Coastguard Worker         num_vcpus: usize,
141*bb4ee6a4SAndroid Build Coastguard Worker         irq_tube: Tube,
142*bb4ee6a4SAndroid Build Coastguard Worker         ioapic_pins: Option<usize>,
143*bb4ee6a4SAndroid Build Coastguard Worker         clock: Arc<Mutex<Clock>>,
144*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Self> {
145*bb4ee6a4SAndroid Build Coastguard Worker         let pit_evt = IrqEdgeEvent::new()?;
146*bb4ee6a4SAndroid Build Coastguard Worker         // For test only, this clock instance is FakeClock. It needs to be cloned for every Timer
147*bb4ee6a4SAndroid Build Coastguard Worker         // instance, so make a clone for it now.
148*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(test)]
149*bb4ee6a4SAndroid Build Coastguard Worker         let test_clock = clock.clone();
150*bb4ee6a4SAndroid Build Coastguard Worker         let pit = Pit::new(pit_evt.try_clone()?, clock).map_err(|e| match e {
151*bb4ee6a4SAndroid Build Coastguard Worker             PitError::CloneEvent(err) => err,
152*bb4ee6a4SAndroid Build Coastguard Worker             PitError::CreateEvent(err) => err,
153*bb4ee6a4SAndroid Build Coastguard Worker             PitError::CreateWaitContext(err) => err,
154*bb4ee6a4SAndroid Build Coastguard Worker             PitError::TimerCreateError(err) => err,
155*bb4ee6a4SAndroid Build Coastguard Worker             PitError::WaitError(err) => err,
156*bb4ee6a4SAndroid Build Coastguard Worker             PitError::SpawnThread(_) => Error::new(libc::EIO),
157*bb4ee6a4SAndroid Build Coastguard Worker         })?;
158*bb4ee6a4SAndroid Build Coastguard Worker         let pit_event_source = IrqEventSource::from_device(&pit);
159*bb4ee6a4SAndroid Build Coastguard Worker 
160*bb4ee6a4SAndroid Build Coastguard Worker         let ioapic_pins = ioapic_pins.unwrap_or(hypervisor::NUM_IOAPIC_PINS);
161*bb4ee6a4SAndroid Build Coastguard Worker         let ioapic = Ioapic::new(irq_tube, ioapic_pins)?;
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker         let mut timer_descriptors: Vec<Descriptor> = Vec::with_capacity(num_vcpus);
164*bb4ee6a4SAndroid Build Coastguard Worker         let mut apics: Vec<Arc<Mutex<Apic>>> = Vec::with_capacity(num_vcpus);
165*bb4ee6a4SAndroid Build Coastguard Worker         for id in 0..num_vcpus {
166*bb4ee6a4SAndroid Build Coastguard Worker             cfg_if::cfg_if! {
167*bb4ee6a4SAndroid Build Coastguard Worker                 if #[cfg(test)] {
168*bb4ee6a4SAndroid Build Coastguard Worker                     let timer = Timer::new(test_clock.clone());
169*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
170*bb4ee6a4SAndroid Build Coastguard Worker                     let timer = Timer::new()?;
171*bb4ee6a4SAndroid Build Coastguard Worker                 }
172*bb4ee6a4SAndroid Build Coastguard Worker             }
173*bb4ee6a4SAndroid Build Coastguard Worker             // Timers are owned by the apics, which outlive the raw descriptors stored here and in
174*bb4ee6a4SAndroid Build Coastguard Worker             // the worker threads.
175*bb4ee6a4SAndroid Build Coastguard Worker             timer_descriptors.push(Descriptor(timer.as_raw_descriptor()));
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker             let id: u8 = id.try_into().or(Err(Error::new(libc::EINVAL)))?;
178*bb4ee6a4SAndroid Build Coastguard Worker             let apic = Apic::new(id, Box::new(timer));
179*bb4ee6a4SAndroid Build Coastguard Worker             apics.push(Arc::new(Mutex::new(apic)));
180*bb4ee6a4SAndroid Build Coastguard Worker         }
181*bb4ee6a4SAndroid Build Coastguard Worker         let dropper = Dropper {
182*bb4ee6a4SAndroid Build Coastguard Worker             workers: Vec::new(),
183*bb4ee6a4SAndroid Build Coastguard Worker         };
184*bb4ee6a4SAndroid Build Coastguard Worker 
185*bb4ee6a4SAndroid Build Coastguard Worker         let mut chip = UserspaceIrqChip {
186*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: Arc::new(Mutex::new(
187*bb4ee6a4SAndroid Build Coastguard Worker                 iter::repeat_with(|| None).take(num_vcpus).collect(),
188*bb4ee6a4SAndroid Build Coastguard Worker             )),
189*bb4ee6a4SAndroid Build Coastguard Worker             waiters: iter::repeat_with(Default::default)
190*bb4ee6a4SAndroid Build Coastguard Worker                 .take(num_vcpus)
191*bb4ee6a4SAndroid Build Coastguard Worker                 .collect(),
192*bb4ee6a4SAndroid Build Coastguard Worker             routes: Arc::new(Mutex::new(Routes::new())),
193*bb4ee6a4SAndroid Build Coastguard Worker             pit: Arc::new(Mutex::new(pit)),
194*bb4ee6a4SAndroid Build Coastguard Worker             pic: Arc::new(Mutex::new(Pic::new())),
195*bb4ee6a4SAndroid Build Coastguard Worker             ioapic: Arc::new(Mutex::new(ioapic)),
196*bb4ee6a4SAndroid Build Coastguard Worker             ioapic_pins,
197*bb4ee6a4SAndroid Build Coastguard Worker             apics,
198*bb4ee6a4SAndroid Build Coastguard Worker             timer_descriptors,
199*bb4ee6a4SAndroid Build Coastguard Worker             delayed_ioapic_irq_events: Arc::new(Mutex::new(DelayedIoApicIrqEvents::new()?)),
200*bb4ee6a4SAndroid Build Coastguard Worker             irq_events: Arc::new(Mutex::new(Vec::new())),
201*bb4ee6a4SAndroid Build Coastguard Worker             dropper: Arc::new(Mutex::new(dropper)),
202*bb4ee6a4SAndroid Build Coastguard Worker             activated: false,
203*bb4ee6a4SAndroid Build Coastguard Worker         };
204*bb4ee6a4SAndroid Build Coastguard Worker 
205*bb4ee6a4SAndroid Build Coastguard Worker         // Setup standard x86 irq routes
206*bb4ee6a4SAndroid Build Coastguard Worker         chip.set_irq_routes(&Routes::default_pic_ioapic_routes(ioapic_pins))?;
207*bb4ee6a4SAndroid Build Coastguard Worker 
208*bb4ee6a4SAndroid Build Coastguard Worker         chip.register_edge_irq_event(PIT_CHANNEL0_IRQ, &pit_evt, pit_event_source)?;
209*bb4ee6a4SAndroid Build Coastguard Worker         Ok(chip)
210*bb4ee6a4SAndroid Build Coastguard Worker     }
211*bb4ee6a4SAndroid Build Coastguard Worker 
212*bb4ee6a4SAndroid Build Coastguard Worker     /// Handles a message from an APIC.
handle_msg(&self, msg: ApicBusMsg)213*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_msg(&self, msg: ApicBusMsg) {
214*bb4ee6a4SAndroid Build Coastguard Worker         match msg {
215*bb4ee6a4SAndroid Build Coastguard Worker             ApicBusMsg::Eoi(vector) => {
216*bb4ee6a4SAndroid Build Coastguard Worker                 let _ = self.broadcast_eoi(vector);
217*bb4ee6a4SAndroid Build Coastguard Worker             }
218*bb4ee6a4SAndroid Build Coastguard Worker             ApicBusMsg::Ipi(interrupt) => self.send_irq_to_apics(&interrupt),
219*bb4ee6a4SAndroid Build Coastguard Worker         }
220*bb4ee6a4SAndroid Build Coastguard Worker     }
221*bb4ee6a4SAndroid Build Coastguard Worker 
222*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends a Message Signaled Interrupt to one or more APICs.  MSIs are a 64-bit address and
223*bb4ee6a4SAndroid Build Coastguard Worker     /// 32-bit data, but in the Intel spec we're implementing, only the low 32 bits of the address
224*bb4ee6a4SAndroid Build Coastguard Worker     /// are used.
send_msi(&self, addr: u32, data: u32)225*bb4ee6a4SAndroid Build Coastguard Worker     fn send_msi(&self, addr: u32, data: u32) {
226*bb4ee6a4SAndroid Build Coastguard Worker         let mut msi_addr = MsiAddressMessage::new();
227*bb4ee6a4SAndroid Build Coastguard Worker         msi_addr.set(0, 32, addr as u64);
228*bb4ee6a4SAndroid Build Coastguard Worker         let dest = match InterruptDestination::try_from(&msi_addr) {
229*bb4ee6a4SAndroid Build Coastguard Worker             Ok(dest) => dest,
230*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
231*bb4ee6a4SAndroid Build Coastguard Worker                 warn!("Invalid MSI message: {}", e);
232*bb4ee6a4SAndroid Build Coastguard Worker                 return;
233*bb4ee6a4SAndroid Build Coastguard Worker             }
234*bb4ee6a4SAndroid Build Coastguard Worker         };
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker         let mut msi_data = MsiDataMessage::new();
237*bb4ee6a4SAndroid Build Coastguard Worker         msi_data.set(0, 32, data as u64);
238*bb4ee6a4SAndroid Build Coastguard Worker         let data = InterruptData::from(&msi_data);
239*bb4ee6a4SAndroid Build Coastguard Worker 
240*bb4ee6a4SAndroid Build Coastguard Worker         self.send_irq_to_apics(&Interrupt { dest, data });
241*bb4ee6a4SAndroid Build Coastguard Worker     }
242*bb4ee6a4SAndroid Build Coastguard Worker 
send_irq_to_apic(&self, id: usize, irq: &InterruptData)243*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_irq_to_apic(&self, id: usize, irq: &InterruptData) {
244*bb4ee6a4SAndroid Build Coastguard Worker         // id can come from the guest, so check bounds.
245*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(apic) = self.apics.get(id) {
246*bb4ee6a4SAndroid Build Coastguard Worker             apic.lock().accept_irq(irq);
247*bb4ee6a4SAndroid Build Coastguard Worker         } else {
248*bb4ee6a4SAndroid Build Coastguard Worker             error!("Interrupt for non-existent apic {}: {:?}", id, irq);
249*bb4ee6a4SAndroid Build Coastguard Worker         }
250*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(Some(vcpu)) = self.vcpus.lock().get(id) {
251*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.set_interrupt_window_requested(true);
252*bb4ee6a4SAndroid Build Coastguard Worker         } else {
253*bb4ee6a4SAndroid Build Coastguard Worker             error!("Interrupt for non-existent vcpu {}: {:?}", id, irq);
254*bb4ee6a4SAndroid Build Coastguard Worker         }
255*bb4ee6a4SAndroid Build Coastguard Worker         self.waiters[id].notify();
256*bb4ee6a4SAndroid Build Coastguard Worker     }
257*bb4ee6a4SAndroid Build Coastguard Worker 
258*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends an interrupt to one or more APICs.  Used for sending MSIs and IPIs.
send_irq_to_apics(&self, irq: &Interrupt)259*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_irq_to_apics(&self, irq: &Interrupt) {
260*bb4ee6a4SAndroid Build Coastguard Worker         match irq.data.delivery {
261*bb4ee6a4SAndroid Build Coastguard Worker             DeliveryMode::Fixed | DeliveryMode::Lowest | DeliveryMode::RemoteRead => {}
262*bb4ee6a4SAndroid Build Coastguard Worker             _ => info!("UserspaceIrqChip received special irq: {:?}", irq),
263*bb4ee6a4SAndroid Build Coastguard Worker         }
264*bb4ee6a4SAndroid Build Coastguard Worker 
265*bb4ee6a4SAndroid Build Coastguard Worker         // First try the fast path, where the destination is a single APIC we can send to directly.
266*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(apic_id) = Apic::single_dest_fast(&irq.dest) {
267*bb4ee6a4SAndroid Build Coastguard Worker             self.send_irq_to_apic(apic_id as usize, &irq.data);
268*bb4ee6a4SAndroid Build Coastguard Worker             return;
269*bb4ee6a4SAndroid Build Coastguard Worker         }
270*bb4ee6a4SAndroid Build Coastguard Worker 
271*bb4ee6a4SAndroid Build Coastguard Worker         let lowest_mode = irq.data.delivery == DeliveryMode::Lowest;
272*bb4ee6a4SAndroid Build Coastguard Worker         let mut lowest_priority = u8::MAX;
273*bb4ee6a4SAndroid Build Coastguard Worker         let mut lowest_apic: Option<usize> = None;
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker         for (i, apic) in self.apics.iter().enumerate() {
276*bb4ee6a4SAndroid Build Coastguard Worker             let send = {
277*bb4ee6a4SAndroid Build Coastguard Worker                 let apic = apic.lock();
278*bb4ee6a4SAndroid Build Coastguard Worker                 if !apic.match_dest(&irq.dest) {
279*bb4ee6a4SAndroid Build Coastguard Worker                     false
280*bb4ee6a4SAndroid Build Coastguard Worker                 } else if lowest_mode {
281*bb4ee6a4SAndroid Build Coastguard Worker                     let priority = apic.get_processor_priority();
282*bb4ee6a4SAndroid Build Coastguard Worker                     if priority <= lowest_priority {
283*bb4ee6a4SAndroid Build Coastguard Worker                         lowest_priority = priority;
284*bb4ee6a4SAndroid Build Coastguard Worker                         lowest_apic = Some(i);
285*bb4ee6a4SAndroid Build Coastguard Worker                     }
286*bb4ee6a4SAndroid Build Coastguard Worker                     false
287*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
288*bb4ee6a4SAndroid Build Coastguard Worker                     true
289*bb4ee6a4SAndroid Build Coastguard Worker                 }
290*bb4ee6a4SAndroid Build Coastguard Worker             };
291*bb4ee6a4SAndroid Build Coastguard Worker             if send {
292*bb4ee6a4SAndroid Build Coastguard Worker                 self.send_irq_to_apic(i, &irq.data);
293*bb4ee6a4SAndroid Build Coastguard Worker             }
294*bb4ee6a4SAndroid Build Coastguard Worker         }
295*bb4ee6a4SAndroid Build Coastguard Worker 
296*bb4ee6a4SAndroid Build Coastguard Worker         if lowest_mode {
297*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(index) = lowest_apic {
298*bb4ee6a4SAndroid Build Coastguard Worker                 self.send_irq_to_apic(index, &irq.data);
299*bb4ee6a4SAndroid Build Coastguard Worker             } else {
300*bb4ee6a4SAndroid Build Coastguard Worker                 // According to sections 10.6.2.1 and 10.6.2.2 of the SDM, the OS should not let
301*bb4ee6a4SAndroid Build Coastguard Worker                 // this happen.  If the OS is misconfigured then drop the interrupt and log a
302*bb4ee6a4SAndroid Build Coastguard Worker                 // warning.
303*bb4ee6a4SAndroid Build Coastguard Worker                 warn!(
304*bb4ee6a4SAndroid Build Coastguard Worker                     "Lowest priority interrupt sent, but no apics configured as valid target: {:?}",
305*bb4ee6a4SAndroid Build Coastguard Worker                     irq
306*bb4ee6a4SAndroid Build Coastguard Worker                 );
307*bb4ee6a4SAndroid Build Coastguard Worker             }
308*bb4ee6a4SAndroid Build Coastguard Worker         }
309*bb4ee6a4SAndroid Build Coastguard Worker     }
310*bb4ee6a4SAndroid Build Coastguard Worker 
311*bb4ee6a4SAndroid Build Coastguard Worker     /// Delivers a startup IPI to `vcpu`.
deliver_startup(&self, vcpu: &V, vector: u8) -> Result<()>312*bb4ee6a4SAndroid Build Coastguard Worker     fn deliver_startup(&self, vcpu: &V, vector: u8) -> Result<()> {
313*bb4ee6a4SAndroid Build Coastguard Worker         // This comes from Intel SDM volume 3, chapter 8.4.  The vector specifies a page aligned
314*bb4ee6a4SAndroid Build Coastguard Worker         // address where execution should start.  cs.base is the offset for the code segment with an
315*bb4ee6a4SAndroid Build Coastguard Worker         // RIP of 0.  The cs.selector is just the base shifted right by 4 bits.
316*bb4ee6a4SAndroid Build Coastguard Worker         let mut sregs = vcpu.get_sregs()?;
317*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cs.base = (vector as u64) << 12;
318*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cs.selector = (vector as u16) << 8;
319*bb4ee6a4SAndroid Build Coastguard Worker 
320*bb4ee6a4SAndroid Build Coastguard Worker         // Set CR0 to its INIT value per the manual.  Application processors won't boot with the CR0
321*bb4ee6a4SAndroid Build Coastguard Worker         // protected mode and paging bits set by setup_sregs().  Kernel APIC doesn't have this
322*bb4ee6a4SAndroid Build Coastguard Worker         // issue, probably because it uses MSRs instead of MMIO, so it's less affected when the AP's
323*bb4ee6a4SAndroid Build Coastguard Worker         // state (CR3 etc.) doesn't reflect changes that Linux made while booting vcpu 0.
324*bb4ee6a4SAndroid Build Coastguard Worker         sregs.cr0 = X86_CR0_INIT;
325*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_sregs(&sregs)?;
326*bb4ee6a4SAndroid Build Coastguard Worker 
327*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = vcpu.get_regs()?;
328*bb4ee6a4SAndroid Build Coastguard Worker         regs.rip = 0;
329*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_regs(&regs)?;
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
332*bb4ee6a4SAndroid Build Coastguard Worker     }
333*bb4ee6a4SAndroid Build Coastguard Worker 
334*bb4ee6a4SAndroid Build Coastguard Worker     /// Checks if the specified VCPU is in a runnable state.
is_runnable(&self, vcpu_id: usize) -> bool335*bb4ee6a4SAndroid Build Coastguard Worker     fn is_runnable(&self, vcpu_id: usize) -> bool {
336*bb4ee6a4SAndroid Build Coastguard Worker         self.apics[vcpu_id].lock().get_mp_state() == MPState::Runnable
337*bb4ee6a4SAndroid Build Coastguard Worker     }
338*bb4ee6a4SAndroid Build Coastguard Worker }
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker impl Dropper {
sleep(&mut self) -> anyhow::Result<()>341*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
342*bb4ee6a4SAndroid Build Coastguard Worker         for thread in self.workers.split_off(0).into_iter() {
343*bb4ee6a4SAndroid Build Coastguard Worker             thread
344*bb4ee6a4SAndroid Build Coastguard Worker                 .stop()
345*bb4ee6a4SAndroid Build Coastguard Worker                 .context("UserspaceIrqChip worker thread exited with error")?;
346*bb4ee6a4SAndroid Build Coastguard Worker         }
347*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
348*bb4ee6a4SAndroid Build Coastguard Worker     }
349*bb4ee6a4SAndroid Build Coastguard Worker }
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> UserspaceIrqChip<V> {
register_irq_event( &mut self, irq: u32, irq_event: &Event, resample_event: Option<&Event>, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>352*bb4ee6a4SAndroid Build Coastguard Worker     fn register_irq_event(
353*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
354*bb4ee6a4SAndroid Build Coastguard Worker         irq: u32,
355*bb4ee6a4SAndroid Build Coastguard Worker         irq_event: &Event,
356*bb4ee6a4SAndroid Build Coastguard Worker         resample_event: Option<&Event>,
357*bb4ee6a4SAndroid Build Coastguard Worker         source: IrqEventSource,
358*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Option<IrqEventIndex>> {
359*bb4ee6a4SAndroid Build Coastguard Worker         let mut evt = IrqEvent {
360*bb4ee6a4SAndroid Build Coastguard Worker             gsi: irq,
361*bb4ee6a4SAndroid Build Coastguard Worker             event: irq_event.try_clone()?,
362*bb4ee6a4SAndroid Build Coastguard Worker             resample_event: None,
363*bb4ee6a4SAndroid Build Coastguard Worker             source,
364*bb4ee6a4SAndroid Build Coastguard Worker         };
365*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(resample_event) = resample_event {
366*bb4ee6a4SAndroid Build Coastguard Worker             evt.resample_event = Some(resample_event.try_clone()?);
367*bb4ee6a4SAndroid Build Coastguard Worker         }
368*bb4ee6a4SAndroid Build Coastguard Worker 
369*bb4ee6a4SAndroid Build Coastguard Worker         let mut irq_events = self.irq_events.lock();
370*bb4ee6a4SAndroid Build Coastguard Worker         let index = irq_events.len();
371*bb4ee6a4SAndroid Build Coastguard Worker         irq_events.push(Some(evt));
372*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Some(index))
373*bb4ee6a4SAndroid Build Coastguard Worker     }
374*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()>375*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()> {
376*bb4ee6a4SAndroid Build Coastguard Worker         let mut irq_events = self.irq_events.lock();
377*bb4ee6a4SAndroid Build Coastguard Worker         for (index, evt) in irq_events.iter().enumerate() {
378*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(evt) = evt {
379*bb4ee6a4SAndroid Build Coastguard Worker                 if evt.gsi == irq && irq_event.eq(&evt.event) {
380*bb4ee6a4SAndroid Build Coastguard Worker                     irq_events[index] = None;
381*bb4ee6a4SAndroid Build Coastguard Worker                     break;
382*bb4ee6a4SAndroid Build Coastguard Worker                 }
383*bb4ee6a4SAndroid Build Coastguard Worker             }
384*bb4ee6a4SAndroid Build Coastguard Worker         }
385*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
386*bb4ee6a4SAndroid Build Coastguard Worker     }
387*bb4ee6a4SAndroid Build Coastguard Worker }
388*bb4ee6a4SAndroid Build Coastguard Worker 
389*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> IrqChip for UserspaceIrqChip<V> {
add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>390*bb4ee6a4SAndroid Build Coastguard Worker     fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()> {
391*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu: &V = vcpu
392*bb4ee6a4SAndroid Build Coastguard Worker             .downcast_ref()
393*bb4ee6a4SAndroid Build Coastguard Worker             .expect("UserspaceIrqChip::add_vcpu called with incorrect vcpu type");
394*bb4ee6a4SAndroid Build Coastguard Worker         self.vcpus.lock()[vcpu_id] = Some(vcpu.try_clone()?);
395*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
396*bb4ee6a4SAndroid Build Coastguard Worker     }
397*bb4ee6a4SAndroid Build Coastguard Worker 
register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>398*bb4ee6a4SAndroid Build Coastguard Worker     fn register_edge_irq_event(
399*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
400*bb4ee6a4SAndroid Build Coastguard Worker         irq: u32,
401*bb4ee6a4SAndroid Build Coastguard Worker         irq_event: &IrqEdgeEvent,
402*bb4ee6a4SAndroid Build Coastguard Worker         source: IrqEventSource,
403*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Option<IrqEventIndex>> {
404*bb4ee6a4SAndroid Build Coastguard Worker         self.register_irq_event(irq, irq_event.get_trigger(), None, source)
405*bb4ee6a4SAndroid Build Coastguard Worker     }
406*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>407*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> {
408*bb4ee6a4SAndroid Build Coastguard Worker         self.unregister_irq_event(irq, irq_event.get_trigger())
409*bb4ee6a4SAndroid Build Coastguard Worker     }
410*bb4ee6a4SAndroid Build Coastguard Worker 
register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>411*bb4ee6a4SAndroid Build Coastguard Worker     fn register_level_irq_event(
412*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
413*bb4ee6a4SAndroid Build Coastguard Worker         irq: u32,
414*bb4ee6a4SAndroid Build Coastguard Worker         irq_event: &IrqLevelEvent,
415*bb4ee6a4SAndroid Build Coastguard Worker         source: IrqEventSource,
416*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Option<IrqEventIndex>> {
417*bb4ee6a4SAndroid Build Coastguard Worker         self.register_irq_event(
418*bb4ee6a4SAndroid Build Coastguard Worker             irq,
419*bb4ee6a4SAndroid Build Coastguard Worker             irq_event.get_trigger(),
420*bb4ee6a4SAndroid Build Coastguard Worker             Some(irq_event.get_resample()),
421*bb4ee6a4SAndroid Build Coastguard Worker             source,
422*bb4ee6a4SAndroid Build Coastguard Worker         )
423*bb4ee6a4SAndroid Build Coastguard Worker     }
424*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>425*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> {
426*bb4ee6a4SAndroid Build Coastguard Worker         self.unregister_irq_event(irq, irq_event.get_trigger())
427*bb4ee6a4SAndroid Build Coastguard Worker     }
428*bb4ee6a4SAndroid Build Coastguard Worker 
route_irq(&mut self, route: IrqRoute) -> Result<()>429*bb4ee6a4SAndroid Build Coastguard Worker     fn route_irq(&mut self, route: IrqRoute) -> Result<()> {
430*bb4ee6a4SAndroid Build Coastguard Worker         self.routes.lock().add(route)
431*bb4ee6a4SAndroid Build Coastguard Worker     }
432*bb4ee6a4SAndroid Build Coastguard Worker 
set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>433*bb4ee6a4SAndroid Build Coastguard Worker     fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()> {
434*bb4ee6a4SAndroid Build Coastguard Worker         self.routes.lock().replace_all(routes)
435*bb4ee6a4SAndroid Build Coastguard Worker     }
436*bb4ee6a4SAndroid Build Coastguard Worker 
irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>437*bb4ee6a4SAndroid Build Coastguard Worker     fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> {
438*bb4ee6a4SAndroid Build Coastguard Worker         let mut tokens: Vec<(IrqEventIndex, IrqEventSource, Event)> = Vec::new();
439*bb4ee6a4SAndroid Build Coastguard Worker         for (index, evt) in self.irq_events.lock().iter().enumerate() {
440*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(evt) = evt {
441*bb4ee6a4SAndroid Build Coastguard Worker                 tokens.push((index, evt.source.clone(), evt.event.try_clone()?));
442*bb4ee6a4SAndroid Build Coastguard Worker             }
443*bb4ee6a4SAndroid Build Coastguard Worker         }
444*bb4ee6a4SAndroid Build Coastguard Worker         Ok(tokens)
445*bb4ee6a4SAndroid Build Coastguard Worker     }
446*bb4ee6a4SAndroid Build Coastguard Worker 
service_irq(&mut self, irq: u32, level: bool) -> Result<()>447*bb4ee6a4SAndroid Build Coastguard Worker     fn service_irq(&mut self, irq: u32, level: bool) -> Result<()> {
448*bb4ee6a4SAndroid Build Coastguard Worker         for route in self.routes.lock()[irq as usize].iter() {
449*bb4ee6a4SAndroid Build Coastguard Worker             match *route {
450*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Irqchip {
451*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::PicPrimary,
452*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
453*bb4ee6a4SAndroid Build Coastguard Worker                 }
454*bb4ee6a4SAndroid Build Coastguard Worker                 | IrqSource::Irqchip {
455*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::PicSecondary,
456*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
457*bb4ee6a4SAndroid Build Coastguard Worker                 } => {
458*bb4ee6a4SAndroid Build Coastguard Worker                     self.pic.lock().service_irq(pin as u8, level);
459*bb4ee6a4SAndroid Build Coastguard Worker                 }
460*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Irqchip {
461*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::Ioapic,
462*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
463*bb4ee6a4SAndroid Build Coastguard Worker                 } => {
464*bb4ee6a4SAndroid Build Coastguard Worker                     self.ioapic.lock().service_irq(pin as usize, level);
465*bb4ee6a4SAndroid Build Coastguard Worker                 }
466*bb4ee6a4SAndroid Build Coastguard Worker                 // service_irq's level parameter is ignored for MSIs.  MSI data specifies the level.
467*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Msi { address, data } => self.send_msi(address as u32, data),
468*bb4ee6a4SAndroid Build Coastguard Worker                 _ => {
469*bb4ee6a4SAndroid Build Coastguard Worker                     error!("Unexpected route source {:?}", route);
470*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::new(libc::EINVAL));
471*bb4ee6a4SAndroid Build Coastguard Worker                 }
472*bb4ee6a4SAndroid Build Coastguard Worker             }
473*bb4ee6a4SAndroid Build Coastguard Worker         }
474*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
475*bb4ee6a4SAndroid Build Coastguard Worker     }
476*bb4ee6a4SAndroid Build Coastguard Worker 
477*bb4ee6a4SAndroid Build Coastguard Worker     /// Services an IRQ event by asserting then deasserting an IRQ line.  The associated Event
478*bb4ee6a4SAndroid Build Coastguard Worker     /// that triggered the irq event will be read from.  If the irq is associated with a resample
479*bb4ee6a4SAndroid Build Coastguard Worker     /// Event, then the deassert will only happen after an EOI is broadcast for a vector
480*bb4ee6a4SAndroid Build Coastguard Worker     /// associated with the irq line.
481*bb4ee6a4SAndroid Build Coastguard Worker     /// For UserspaceIrqChip, this function identifies the destination(s) of the irq: PIC, IOAPIC,
482*bb4ee6a4SAndroid Build Coastguard Worker     /// or APIC (MSI).  If it's a PIC or IOAPIC route, we attempt to call service_irq on those
483*bb4ee6a4SAndroid Build Coastguard Worker     /// chips.  If the IOAPIC is unable to be immediately locked, we add the irq to the
484*bb4ee6a4SAndroid Build Coastguard Worker     /// delayed_ioapic_irq_events (though we still read from the Event that triggered the irq
485*bb4ee6a4SAndroid Build Coastguard Worker     /// event).  If it's an MSI route, we call send_msi to decode the MSI and send it to the
486*bb4ee6a4SAndroid Build Coastguard Worker     /// destination APIC(s).
service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>487*bb4ee6a4SAndroid Build Coastguard Worker     fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()> {
488*bb4ee6a4SAndroid Build Coastguard Worker         let irq_events = self.irq_events.lock();
489*bb4ee6a4SAndroid Build Coastguard Worker         let evt = if let Some(evt) = &irq_events[event_index] {
490*bb4ee6a4SAndroid Build Coastguard Worker             evt
491*bb4ee6a4SAndroid Build Coastguard Worker         } else {
492*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
493*bb4ee6a4SAndroid Build Coastguard Worker         };
494*bb4ee6a4SAndroid Build Coastguard Worker         evt.event.wait()?;
495*bb4ee6a4SAndroid Build Coastguard Worker 
496*bb4ee6a4SAndroid Build Coastguard Worker         for route in self.routes.lock()[evt.gsi as usize].iter() {
497*bb4ee6a4SAndroid Build Coastguard Worker             match *route {
498*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Irqchip {
499*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::PicPrimary,
500*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
501*bb4ee6a4SAndroid Build Coastguard Worker                 }
502*bb4ee6a4SAndroid Build Coastguard Worker                 | IrqSource::Irqchip {
503*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::PicSecondary,
504*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
505*bb4ee6a4SAndroid Build Coastguard Worker                 } => {
506*bb4ee6a4SAndroid Build Coastguard Worker                     let mut pic = self.pic.lock();
507*bb4ee6a4SAndroid Build Coastguard Worker                     if evt.resample_event.is_some() {
508*bb4ee6a4SAndroid Build Coastguard Worker                         pic.service_irq(pin as u8, true);
509*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
510*bb4ee6a4SAndroid Build Coastguard Worker                         pic.service_irq(pin as u8, true);
511*bb4ee6a4SAndroid Build Coastguard Worker                         pic.service_irq(pin as u8, false);
512*bb4ee6a4SAndroid Build Coastguard Worker                     }
513*bb4ee6a4SAndroid Build Coastguard Worker                 }
514*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Irqchip {
515*bb4ee6a4SAndroid Build Coastguard Worker                     chip: IrqSourceChip::Ioapic,
516*bb4ee6a4SAndroid Build Coastguard Worker                     pin,
517*bb4ee6a4SAndroid Build Coastguard Worker                 } => {
518*bb4ee6a4SAndroid Build Coastguard Worker                     if let Ok(mut ioapic) = self.ioapic.try_lock() {
519*bb4ee6a4SAndroid Build Coastguard Worker                         if evt.resample_event.is_some() {
520*bb4ee6a4SAndroid Build Coastguard Worker                             ioapic.service_irq(pin as usize, true);
521*bb4ee6a4SAndroid Build Coastguard Worker                         } else {
522*bb4ee6a4SAndroid Build Coastguard Worker                             ioapic.service_irq(pin as usize, true);
523*bb4ee6a4SAndroid Build Coastguard Worker                             ioapic.service_irq(pin as usize, false);
524*bb4ee6a4SAndroid Build Coastguard Worker                         }
525*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
526*bb4ee6a4SAndroid Build Coastguard Worker                         let mut delayed_events = self.delayed_ioapic_irq_events.lock();
527*bb4ee6a4SAndroid Build Coastguard Worker                         delayed_events.events.push(event_index);
528*bb4ee6a4SAndroid Build Coastguard Worker                         delayed_events.trigger.signal().unwrap();
529*bb4ee6a4SAndroid Build Coastguard Worker                     }
530*bb4ee6a4SAndroid Build Coastguard Worker                 }
531*bb4ee6a4SAndroid Build Coastguard Worker                 IrqSource::Msi { address, data } => self.send_msi(address as u32, data),
532*bb4ee6a4SAndroid Build Coastguard Worker                 _ => {
533*bb4ee6a4SAndroid Build Coastguard Worker                     error!("Unexpected route source {:?}", route);
534*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::new(libc::EINVAL));
535*bb4ee6a4SAndroid Build Coastguard Worker                 }
536*bb4ee6a4SAndroid Build Coastguard Worker             }
537*bb4ee6a4SAndroid Build Coastguard Worker         }
538*bb4ee6a4SAndroid Build Coastguard Worker 
539*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
540*bb4ee6a4SAndroid Build Coastguard Worker     }
541*bb4ee6a4SAndroid Build Coastguard Worker 
542*bb4ee6a4SAndroid Build Coastguard Worker     /// Broadcasts an end of interrupt.  For UserspaceIrqChip this sends the EOI to the ioapic.
broadcast_eoi(&self, vector: u8) -> Result<()>543*bb4ee6a4SAndroid Build Coastguard Worker     fn broadcast_eoi(&self, vector: u8) -> Result<()> {
544*bb4ee6a4SAndroid Build Coastguard Worker         self.ioapic.lock().end_of_interrupt(vector);
545*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
546*bb4ee6a4SAndroid Build Coastguard Worker     }
547*bb4ee6a4SAndroid Build Coastguard Worker 
548*bb4ee6a4SAndroid Build Coastguard Worker     /// Injects any pending interrupts for `vcpu`.
549*bb4ee6a4SAndroid Build Coastguard Worker     ///
550*bb4ee6a4SAndroid Build Coastguard Worker     /// For UserspaceIrqChip this:
551*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Injects a PIC interrupt, if vcpu_id is 0 and vcpu is ready for interrupt
552*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Injects an APIC fixed interrupt, if vcpu is ready for interrupt and PIC didn't inject
553*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Injects APIC NMIs
554*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Handles APIC INIT IPIs
555*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Handles APIC SIPIs
556*bb4ee6a4SAndroid Build Coastguard Worker     ///   * Requests an interrupt window, if PIC or APIC still has pending interrupts for this vcpu
inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>557*bb4ee6a4SAndroid Build Coastguard Worker     fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()> {
558*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu: &V = vcpu
559*bb4ee6a4SAndroid Build Coastguard Worker             .downcast_ref()
560*bb4ee6a4SAndroid Build Coastguard Worker             .expect("UserspaceIrqChip::add_vcpu called with incorrect vcpu type");
561*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_id = vcpu.id();
562*bb4ee6a4SAndroid Build Coastguard Worker         let mut vcpu_ready = vcpu.ready_for_interrupt();
563*bb4ee6a4SAndroid Build Coastguard Worker 
564*bb4ee6a4SAndroid Build Coastguard Worker         let mut pic_needs_window = false;
565*bb4ee6a4SAndroid Build Coastguard Worker         if vcpu_id == 0 {
566*bb4ee6a4SAndroid Build Coastguard Worker             let mut pic = self.pic.lock();
567*bb4ee6a4SAndroid Build Coastguard Worker             if vcpu_ready {
568*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(vector) = pic.get_external_interrupt() {
569*bb4ee6a4SAndroid Build Coastguard Worker                     vcpu.interrupt(vector)?;
570*bb4ee6a4SAndroid Build Coastguard Worker                     self.apics[vcpu_id].lock().set_mp_state(&MPState::Runnable);
571*bb4ee6a4SAndroid Build Coastguard Worker                     // Already injected a PIC interrupt, so APIC fixed interrupt can't be injected.
572*bb4ee6a4SAndroid Build Coastguard Worker                     vcpu_ready = false;
573*bb4ee6a4SAndroid Build Coastguard Worker                 }
574*bb4ee6a4SAndroid Build Coastguard Worker             }
575*bb4ee6a4SAndroid Build Coastguard Worker             pic_needs_window = pic.interrupt_requested();
576*bb4ee6a4SAndroid Build Coastguard Worker         }
577*bb4ee6a4SAndroid Build Coastguard Worker 
578*bb4ee6a4SAndroid Build Coastguard Worker         let irqs = self.apics[vcpu_id].lock().get_pending_irqs(vcpu_ready);
579*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(vector) = irqs.fixed {
580*bb4ee6a4SAndroid Build Coastguard Worker             let do_interrupt = {
581*bb4ee6a4SAndroid Build Coastguard Worker                 let mut apic = self.apics[vcpu_id].lock();
582*bb4ee6a4SAndroid Build Coastguard Worker                 match apic.get_mp_state() {
583*bb4ee6a4SAndroid Build Coastguard Worker                     MPState::Runnable | MPState::Halted => {
584*bb4ee6a4SAndroid Build Coastguard Worker                         // APIC interrupts should only be injectable when the MPState is
585*bb4ee6a4SAndroid Build Coastguard Worker                         // Halted or Runnable.
586*bb4ee6a4SAndroid Build Coastguard Worker                         apic.set_mp_state(&MPState::Runnable);
587*bb4ee6a4SAndroid Build Coastguard Worker                         true
588*bb4ee6a4SAndroid Build Coastguard Worker                     }
589*bb4ee6a4SAndroid Build Coastguard Worker                     s => {
590*bb4ee6a4SAndroid Build Coastguard Worker                         // This shouldn't happen, but log a helpful error if it does.
591*bb4ee6a4SAndroid Build Coastguard Worker                         error!("Interrupt cannot be injected while in state: {:?}", s);
592*bb4ee6a4SAndroid Build Coastguard Worker                         false
593*bb4ee6a4SAndroid Build Coastguard Worker                     }
594*bb4ee6a4SAndroid Build Coastguard Worker                 }
595*bb4ee6a4SAndroid Build Coastguard Worker             };
596*bb4ee6a4SAndroid Build Coastguard Worker 
597*bb4ee6a4SAndroid Build Coastguard Worker             if do_interrupt {
598*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu.interrupt(vector)?;
599*bb4ee6a4SAndroid Build Coastguard Worker             }
600*bb4ee6a4SAndroid Build Coastguard Worker         }
601*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..irqs.nmis {
602*bb4ee6a4SAndroid Build Coastguard Worker             let prev_state = self.apics[vcpu_id].lock().get_mp_state();
603*bb4ee6a4SAndroid Build Coastguard Worker             vcpu.inject_nmi()?;
604*bb4ee6a4SAndroid Build Coastguard Worker             self.apics[vcpu_id].lock().set_mp_state(&MPState::Runnable);
605*bb4ee6a4SAndroid Build Coastguard Worker             info!(
606*bb4ee6a4SAndroid Build Coastguard Worker                 "Delivered NMI to cpu {}, mp_state was {:?}, now is {:?}",
607*bb4ee6a4SAndroid Build Coastguard Worker                 vcpu_id,
608*bb4ee6a4SAndroid Build Coastguard Worker                 prev_state,
609*bb4ee6a4SAndroid Build Coastguard Worker                 MPState::Runnable
610*bb4ee6a4SAndroid Build Coastguard Worker             );
611*bb4ee6a4SAndroid Build Coastguard Worker         }
612*bb4ee6a4SAndroid Build Coastguard Worker         if irqs.init {
613*bb4ee6a4SAndroid Build Coastguard Worker             {
614*bb4ee6a4SAndroid Build Coastguard Worker                 let mut apic = self.apics[vcpu_id].lock();
615*bb4ee6a4SAndroid Build Coastguard Worker                 apic.load_reset_state();
616*bb4ee6a4SAndroid Build Coastguard Worker                 apic.set_mp_state(&MPState::InitReceived);
617*bb4ee6a4SAndroid Build Coastguard Worker             }
618*bb4ee6a4SAndroid Build Coastguard Worker             info!("Delivered INIT IPI to cpu {}", vcpu_id);
619*bb4ee6a4SAndroid Build Coastguard Worker         }
620*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(vector) = irqs.startup {
621*bb4ee6a4SAndroid Build Coastguard Worker             // If our state is not MPState::InitReceived then this is probably
622*bb4ee6a4SAndroid Build Coastguard Worker             // the second SIPI in the INIT-SIPI-SIPI sequence; ignore.
623*bb4ee6a4SAndroid Build Coastguard Worker             if self.apics[vcpu_id].lock().get_mp_state() == MPState::InitReceived {
624*bb4ee6a4SAndroid Build Coastguard Worker                 self.deliver_startup(vcpu, vector)?;
625*bb4ee6a4SAndroid Build Coastguard Worker                 self.apics[vcpu_id].lock().set_mp_state(&MPState::Runnable);
626*bb4ee6a4SAndroid Build Coastguard Worker                 info!("Delivered SIPI to cpu {}", vcpu_id);
627*bb4ee6a4SAndroid Build Coastguard Worker             }
628*bb4ee6a4SAndroid Build Coastguard Worker         }
629*bb4ee6a4SAndroid Build Coastguard Worker 
630*bb4ee6a4SAndroid Build Coastguard Worker         let needs_window = pic_needs_window || irqs.needs_window;
631*bb4ee6a4SAndroid Build Coastguard Worker         vcpu.set_interrupt_window_requested(needs_window);
632*bb4ee6a4SAndroid Build Coastguard Worker 
633*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
634*bb4ee6a4SAndroid Build Coastguard Worker     }
635*bb4ee6a4SAndroid Build Coastguard Worker 
636*bb4ee6a4SAndroid Build Coastguard Worker     /// Notifies the irq chip that the specified VCPU has executed a halt instruction.
637*bb4ee6a4SAndroid Build Coastguard Worker     /// For `UserspaceIrqChip`, it sets the APIC's mp_state to `MPState::Halted`.
halted(&self, vcpu_id: usize)638*bb4ee6a4SAndroid Build Coastguard Worker     fn halted(&self, vcpu_id: usize) {
639*bb4ee6a4SAndroid Build Coastguard Worker         self.apics[vcpu_id].lock().set_mp_state(&MPState::Halted)
640*bb4ee6a4SAndroid Build Coastguard Worker     }
641*bb4ee6a4SAndroid Build Coastguard Worker 
642*bb4ee6a4SAndroid Build Coastguard Worker     /// Blocks until `vcpu` is in a runnable state or until interrupted by
643*bb4ee6a4SAndroid Build Coastguard Worker     /// `IrqChip::kick_halted_vcpus`.  Returns `VcpuRunState::Runnable if vcpu is runnable, or
644*bb4ee6a4SAndroid Build Coastguard Worker     /// `VcpuRunState::Interrupted` if the wait was interrupted.
645*bb4ee6a4SAndroid Build Coastguard Worker     /// For `UserspaceIrqChip`, if the APIC isn't `MPState::Runnable`, sleep until there are new
646*bb4ee6a4SAndroid Build Coastguard Worker     /// interrupts pending on the APIC, inject the interrupts, and go back to sleep if still not
647*bb4ee6a4SAndroid Build Coastguard Worker     /// runnable.
wait_until_runnable(&self, vcpu: &dyn Vcpu) -> Result<VcpuRunState>648*bb4ee6a4SAndroid Build Coastguard Worker     fn wait_until_runnable(&self, vcpu: &dyn Vcpu) -> Result<VcpuRunState> {
649*bb4ee6a4SAndroid Build Coastguard Worker         let vcpu_id = vcpu.id();
650*bb4ee6a4SAndroid Build Coastguard Worker         let waiter = &self.waiters[vcpu_id];
651*bb4ee6a4SAndroid Build Coastguard Worker         let mut interrupted_lock = waiter.mtx.lock();
652*bb4ee6a4SAndroid Build Coastguard Worker         loop {
653*bb4ee6a4SAndroid Build Coastguard Worker             if *interrupted_lock {
654*bb4ee6a4SAndroid Build Coastguard Worker                 *interrupted_lock = false;
655*bb4ee6a4SAndroid Build Coastguard Worker                 info!("wait_until_runnable interrupted on cpu {}", vcpu_id);
656*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(VcpuRunState::Interrupted);
657*bb4ee6a4SAndroid Build Coastguard Worker             }
658*bb4ee6a4SAndroid Build Coastguard Worker             if self.is_runnable(vcpu_id) {
659*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(VcpuRunState::Runnable);
660*bb4ee6a4SAndroid Build Coastguard Worker             }
661*bb4ee6a4SAndroid Build Coastguard Worker 
662*bb4ee6a4SAndroid Build Coastguard Worker             self.inject_interrupts(vcpu)?;
663*bb4ee6a4SAndroid Build Coastguard Worker             if self.is_runnable(vcpu_id) {
664*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(VcpuRunState::Runnable);
665*bb4ee6a4SAndroid Build Coastguard Worker             }
666*bb4ee6a4SAndroid Build Coastguard Worker             interrupted_lock = waiter.cvar.wait(interrupted_lock);
667*bb4ee6a4SAndroid Build Coastguard Worker         }
668*bb4ee6a4SAndroid Build Coastguard Worker     }
669*bb4ee6a4SAndroid Build Coastguard Worker 
670*bb4ee6a4SAndroid Build Coastguard Worker     /// Makes unrunnable VCPUs return immediately from `wait_until_runnable`.
671*bb4ee6a4SAndroid Build Coastguard Worker     /// For UserspaceIrqChip, every vcpu gets kicked so its current or next call to
672*bb4ee6a4SAndroid Build Coastguard Worker     /// `wait_until_runnable` will immediately return false.  After that one kick, subsequent
673*bb4ee6a4SAndroid Build Coastguard Worker     /// `wait_until_runnable` calls go back to waiting for runnability normally.
kick_halted_vcpus(&self)674*bb4ee6a4SAndroid Build Coastguard Worker     fn kick_halted_vcpus(&self) {
675*bb4ee6a4SAndroid Build Coastguard Worker         for waiter in self.waiters.iter() {
676*bb4ee6a4SAndroid Build Coastguard Worker             waiter.set_and_notify(/* interrupted= */ true);
677*bb4ee6a4SAndroid Build Coastguard Worker         }
678*bb4ee6a4SAndroid Build Coastguard Worker     }
679*bb4ee6a4SAndroid Build Coastguard Worker 
get_mp_state(&self, vcpu_id: usize) -> Result<MPState>680*bb4ee6a4SAndroid Build Coastguard Worker     fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState> {
681*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.apics[vcpu_id].lock().get_mp_state())
682*bb4ee6a4SAndroid Build Coastguard Worker     }
683*bb4ee6a4SAndroid Build Coastguard Worker 
set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>684*bb4ee6a4SAndroid Build Coastguard Worker     fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()> {
685*bb4ee6a4SAndroid Build Coastguard Worker         self.apics[vcpu_id].lock().set_mp_state(state);
686*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
687*bb4ee6a4SAndroid Build Coastguard Worker     }
688*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<Self>689*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<Self> {
690*bb4ee6a4SAndroid Build Coastguard Worker         // kill_evts and timer_descriptors don't change, so they could be a plain Vec with each
691*bb4ee6a4SAndroid Build Coastguard Worker         // element cloned.  But the Arc<Mutex> avoids a quadratic number of open descriptors from
692*bb4ee6a4SAndroid Build Coastguard Worker         // cloning, and those fields aren't performance critical.
693*bb4ee6a4SAndroid Build Coastguard Worker         Ok(UserspaceIrqChip {
694*bb4ee6a4SAndroid Build Coastguard Worker             vcpus: self.vcpus.clone(),
695*bb4ee6a4SAndroid Build Coastguard Worker             waiters: self.waiters.clone(),
696*bb4ee6a4SAndroid Build Coastguard Worker             routes: self.routes.clone(),
697*bb4ee6a4SAndroid Build Coastguard Worker             pit: self.pit.clone(),
698*bb4ee6a4SAndroid Build Coastguard Worker             pic: self.pic.clone(),
699*bb4ee6a4SAndroid Build Coastguard Worker             ioapic: self.ioapic.clone(),
700*bb4ee6a4SAndroid Build Coastguard Worker             ioapic_pins: self.ioapic_pins,
701*bb4ee6a4SAndroid Build Coastguard Worker             apics: self.apics.clone(),
702*bb4ee6a4SAndroid Build Coastguard Worker             timer_descriptors: self.timer_descriptors.clone(),
703*bb4ee6a4SAndroid Build Coastguard Worker             delayed_ioapic_irq_events: self.delayed_ioapic_irq_events.clone(),
704*bb4ee6a4SAndroid Build Coastguard Worker             irq_events: self.irq_events.clone(),
705*bb4ee6a4SAndroid Build Coastguard Worker             dropper: self.dropper.clone(),
706*bb4ee6a4SAndroid Build Coastguard Worker             activated: self.activated,
707*bb4ee6a4SAndroid Build Coastguard Worker         })
708*bb4ee6a4SAndroid Build Coastguard Worker     }
709*bb4ee6a4SAndroid Build Coastguard Worker 
710*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(srichman): factor out UserspaceIrqChip and KvmSplitIrqChip::finalize_devices
finalize_devices( &mut self, resources: &mut SystemAllocator, io_bus: &Bus, mmio_bus: &Bus, ) -> Result<()>711*bb4ee6a4SAndroid Build Coastguard Worker     fn finalize_devices(
712*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
713*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
714*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: &Bus,
715*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus: &Bus,
716*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
717*bb4ee6a4SAndroid Build Coastguard Worker         // Insert pit into io_bus
718*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(self.pit.clone(), 0x040, 0x8).unwrap();
719*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(self.pit.clone(), 0x061, 0x1).unwrap();
720*bb4ee6a4SAndroid Build Coastguard Worker 
721*bb4ee6a4SAndroid Build Coastguard Worker         // Insert pic into io_bus
722*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(self.pic.clone(), 0x20, 0x2).unwrap();
723*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(self.pic.clone(), 0xa0, 0x2).unwrap();
724*bb4ee6a4SAndroid Build Coastguard Worker         io_bus.insert(self.pic.clone(), 0x4d0, 0x2).unwrap();
725*bb4ee6a4SAndroid Build Coastguard Worker 
726*bb4ee6a4SAndroid Build Coastguard Worker         // Insert ioapic into mmio_bus
727*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
728*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
729*bb4ee6a4SAndroid Build Coastguard Worker                 self.ioapic.clone(),
730*bb4ee6a4SAndroid Build Coastguard Worker                 IOAPIC_BASE_ADDRESS,
731*bb4ee6a4SAndroid Build Coastguard Worker                 IOAPIC_MEM_LENGTH_BYTES,
732*bb4ee6a4SAndroid Build Coastguard Worker             )
733*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
734*bb4ee6a4SAndroid Build Coastguard Worker 
735*bb4ee6a4SAndroid Build Coastguard Worker         // Insert self into mmio_bus for handling APIC mmio
736*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus
737*bb4ee6a4SAndroid Build Coastguard Worker             .insert_sync(
738*bb4ee6a4SAndroid Build Coastguard Worker                 Arc::new(self.try_clone()?),
739*bb4ee6a4SAndroid Build Coastguard Worker                 APIC_BASE_ADDRESS,
740*bb4ee6a4SAndroid Build Coastguard Worker                 APIC_MEM_LENGTH_BYTES,
741*bb4ee6a4SAndroid Build Coastguard Worker             )
742*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
743*bb4ee6a4SAndroid Build Coastguard Worker 
744*bb4ee6a4SAndroid Build Coastguard Worker         // At this point, all of our devices have been created and they have registered their
745*bb4ee6a4SAndroid Build Coastguard Worker         // irq events, so we can clone our resample events
746*bb4ee6a4SAndroid Build Coastguard Worker         let mut ioapic_resample_events: Vec<Vec<Event>> =
747*bb4ee6a4SAndroid Build Coastguard Worker             (0..self.ioapic_pins).map(|_| Vec::new()).collect();
748*bb4ee6a4SAndroid Build Coastguard Worker         let mut pic_resample_events: Vec<Vec<Event>> =
749*bb4ee6a4SAndroid Build Coastguard Worker             (0..self.ioapic_pins).map(|_| Vec::new()).collect();
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker         for evt in self.irq_events.lock().iter().flatten() {
752*bb4ee6a4SAndroid Build Coastguard Worker             if (evt.gsi as usize) >= self.ioapic_pins {
753*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
754*bb4ee6a4SAndroid Build Coastguard Worker             }
755*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(resample_evt) = &evt.resample_event {
756*bb4ee6a4SAndroid Build Coastguard Worker                 ioapic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
757*bb4ee6a4SAndroid Build Coastguard Worker                 pic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
758*bb4ee6a4SAndroid Build Coastguard Worker             }
759*bb4ee6a4SAndroid Build Coastguard Worker         }
760*bb4ee6a4SAndroid Build Coastguard Worker 
761*bb4ee6a4SAndroid Build Coastguard Worker         // Register resample events with the ioapic
762*bb4ee6a4SAndroid Build Coastguard Worker         self.ioapic
763*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
764*bb4ee6a4SAndroid Build Coastguard Worker             .register_resample_events(ioapic_resample_events);
765*bb4ee6a4SAndroid Build Coastguard Worker         // Register resample events with the pic
766*bb4ee6a4SAndroid Build Coastguard Worker         self.pic
767*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
768*bb4ee6a4SAndroid Build Coastguard Worker             .register_resample_events(pic_resample_events);
769*bb4ee6a4SAndroid Build Coastguard Worker 
770*bb4ee6a4SAndroid Build Coastguard Worker         // Make sure all future irq numbers are >= self.ioapic_pins
771*bb4ee6a4SAndroid Build Coastguard Worker         let mut irq_num = resources.allocate_irq().unwrap();
772*bb4ee6a4SAndroid Build Coastguard Worker         while irq_num < self.ioapic_pins as u32 {
773*bb4ee6a4SAndroid Build Coastguard Worker             irq_num = resources.allocate_irq().unwrap();
774*bb4ee6a4SAndroid Build Coastguard Worker         }
775*bb4ee6a4SAndroid Build Coastguard Worker 
776*bb4ee6a4SAndroid Build Coastguard Worker         // Spawn timer threads here instead of in new(), in case crosvm is in sandbox mode.
777*bb4ee6a4SAndroid Build Coastguard Worker         self.activated = true;
778*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.wake();
779*bb4ee6a4SAndroid Build Coastguard Worker 
780*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
781*bb4ee6a4SAndroid Build Coastguard Worker     }
782*bb4ee6a4SAndroid Build Coastguard Worker 
783*bb4ee6a4SAndroid Build Coastguard Worker     /// The UserspaceIrqChip's ioapic may be locked because a vcpu thread is currently writing to
784*bb4ee6a4SAndroid Build Coastguard Worker     /// the ioapic, and the ioapic may be blocking on adding MSI routes, which requires blocking
785*bb4ee6a4SAndroid Build Coastguard Worker     /// tube communication back to the main thread.  Thus, we do not want the main thread to
786*bb4ee6a4SAndroid Build Coastguard Worker     /// block on a locked ioapic, so any irqs that could not be serviced because the ioapic could
787*bb4ee6a4SAndroid Build Coastguard Worker     /// not be immediately locked are added to the delayed_ioapic_irq_events Vec. This function
788*bb4ee6a4SAndroid Build Coastguard Worker     /// processes each delayed event in the vec each time it's called. If the ioapic is still
789*bb4ee6a4SAndroid Build Coastguard Worker     /// locked, we keep the queued irqs for the next time this function is called.
process_delayed_irq_events(&mut self) -> Result<()>790*bb4ee6a4SAndroid Build Coastguard Worker     fn process_delayed_irq_events(&mut self) -> Result<()> {
791*bb4ee6a4SAndroid Build Coastguard Worker         let irq_events = self.irq_events.lock();
792*bb4ee6a4SAndroid Build Coastguard Worker         let mut delayed_events = self.delayed_ioapic_irq_events.lock();
793*bb4ee6a4SAndroid Build Coastguard Worker         delayed_events.events.retain(|&event_index| {
794*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(evt) = &irq_events[event_index] {
795*bb4ee6a4SAndroid Build Coastguard Worker                 if let Ok(mut ioapic) = self.ioapic.try_lock() {
796*bb4ee6a4SAndroid Build Coastguard Worker                     if evt.resample_event.is_some() {
797*bb4ee6a4SAndroid Build Coastguard Worker                         ioapic.service_irq(evt.gsi as usize, true);
798*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
799*bb4ee6a4SAndroid Build Coastguard Worker                         ioapic.service_irq(evt.gsi as usize, true);
800*bb4ee6a4SAndroid Build Coastguard Worker                         ioapic.service_irq(evt.gsi as usize, false);
801*bb4ee6a4SAndroid Build Coastguard Worker                     }
802*bb4ee6a4SAndroid Build Coastguard Worker 
803*bb4ee6a4SAndroid Build Coastguard Worker                     false
804*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
805*bb4ee6a4SAndroid Build Coastguard Worker                     true
806*bb4ee6a4SAndroid Build Coastguard Worker                 }
807*bb4ee6a4SAndroid Build Coastguard Worker             } else {
808*bb4ee6a4SAndroid Build Coastguard Worker                 true
809*bb4ee6a4SAndroid Build Coastguard Worker             }
810*bb4ee6a4SAndroid Build Coastguard Worker         });
811*bb4ee6a4SAndroid Build Coastguard Worker 
812*bb4ee6a4SAndroid Build Coastguard Worker         if delayed_events.events.is_empty() {
813*bb4ee6a4SAndroid Build Coastguard Worker             delayed_events.trigger.wait()?;
814*bb4ee6a4SAndroid Build Coastguard Worker         }
815*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
816*bb4ee6a4SAndroid Build Coastguard Worker     }
817*bb4ee6a4SAndroid Build Coastguard Worker 
irq_delayed_event_token(&self) -> Result<Option<Event>>818*bb4ee6a4SAndroid Build Coastguard Worker     fn irq_delayed_event_token(&self) -> Result<Option<Event>> {
819*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Some(
820*bb4ee6a4SAndroid Build Coastguard Worker             self.delayed_ioapic_irq_events.lock().trigger.try_clone()?,
821*bb4ee6a4SAndroid Build Coastguard Worker         ))
822*bb4ee6a4SAndroid Build Coastguard Worker     }
823*bb4ee6a4SAndroid Build Coastguard Worker 
check_capability(&self, c: IrqChipCap) -> bool824*bb4ee6a4SAndroid Build Coastguard Worker     fn check_capability(&self, c: IrqChipCap) -> bool {
825*bb4ee6a4SAndroid Build Coastguard Worker         match c {
826*bb4ee6a4SAndroid Build Coastguard Worker             IrqChipCap::TscDeadlineTimer => false,
827*bb4ee6a4SAndroid Build Coastguard Worker             IrqChipCap::X2Apic => false,
828*bb4ee6a4SAndroid Build Coastguard Worker             IrqChipCap::MpStateGetSet => true,
829*bb4ee6a4SAndroid Build Coastguard Worker         }
830*bb4ee6a4SAndroid Build Coastguard Worker     }
831*bb4ee6a4SAndroid Build Coastguard Worker }
832*bb4ee6a4SAndroid Build Coastguard Worker 
833*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> BusDevice for UserspaceIrqChip<V> {
debug_label(&self) -> String834*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
835*bb4ee6a4SAndroid Build Coastguard Worker         "UserspaceIrqChip APIC".to_string()
836*bb4ee6a4SAndroid Build Coastguard Worker     }
device_id(&self) -> DeviceId837*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
838*bb4ee6a4SAndroid Build Coastguard Worker         CrosvmDeviceId::UserspaceIrqChip.into()
839*bb4ee6a4SAndroid Build Coastguard Worker     }
840*bb4ee6a4SAndroid Build Coastguard Worker }
841*bb4ee6a4SAndroid Build Coastguard Worker 
842*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> Suspendable for UserspaceIrqChip<V> {
sleep(&mut self) -> anyhow::Result<()>843*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
844*bb4ee6a4SAndroid Build Coastguard Worker         let mut dropper = self.dropper.lock();
845*bb4ee6a4SAndroid Build Coastguard Worker         dropper.sleep()
846*bb4ee6a4SAndroid Build Coastguard Worker     }
847*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>848*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
849*bb4ee6a4SAndroid Build Coastguard Worker         if self.activated {
850*bb4ee6a4SAndroid Build Coastguard Worker             // create workers and run them.
851*bb4ee6a4SAndroid Build Coastguard Worker             let mut dropper = self.dropper.lock();
852*bb4ee6a4SAndroid Build Coastguard Worker             for (i, descriptor) in self.timer_descriptors.iter().enumerate() {
853*bb4ee6a4SAndroid Build Coastguard Worker                 let mut worker = TimerWorker {
854*bb4ee6a4SAndroid Build Coastguard Worker                     id: i,
855*bb4ee6a4SAndroid Build Coastguard Worker                     apic: self.apics[i].clone(),
856*bb4ee6a4SAndroid Build Coastguard Worker                     descriptor: *descriptor,
857*bb4ee6a4SAndroid Build Coastguard Worker                     vcpus: self.vcpus.clone(),
858*bb4ee6a4SAndroid Build Coastguard Worker                     waiter: self.waiters[i].clone(),
859*bb4ee6a4SAndroid Build Coastguard Worker                 };
860*bb4ee6a4SAndroid Build Coastguard Worker                 let worker_thread = WorkerThread::start(
861*bb4ee6a4SAndroid Build Coastguard Worker                     format!("UserspaceIrqChip timer worker {}", i),
862*bb4ee6a4SAndroid Build Coastguard Worker                     move |evt| worker.run(evt),
863*bb4ee6a4SAndroid Build Coastguard Worker                 );
864*bb4ee6a4SAndroid Build Coastguard Worker                 dropper.workers.push(worker_thread);
865*bb4ee6a4SAndroid Build Coastguard Worker             }
866*bb4ee6a4SAndroid Build Coastguard Worker         }
867*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
868*bb4ee6a4SAndroid Build Coastguard Worker     }
869*bb4ee6a4SAndroid Build Coastguard Worker }
870*bb4ee6a4SAndroid Build Coastguard Worker 
871*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> BusDeviceSync for UserspaceIrqChip<V> {
read(&self, info: BusAccessInfo, data: &mut [u8])872*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&self, info: BusAccessInfo, data: &mut [u8]) {
873*bb4ee6a4SAndroid Build Coastguard Worker         self.apics[info.id].lock().read(info.offset, data)
874*bb4ee6a4SAndroid Build Coastguard Worker     }
write(&self, info: BusAccessInfo, data: &[u8])875*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&self, info: BusAccessInfo, data: &[u8]) {
876*bb4ee6a4SAndroid Build Coastguard Worker         let msg = self.apics[info.id].lock().write(info.offset, data);
877*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(m) = msg {
878*bb4ee6a4SAndroid Build Coastguard Worker             self.handle_msg(m);
879*bb4ee6a4SAndroid Build Coastguard Worker         }
880*bb4ee6a4SAndroid Build Coastguard Worker     }
881*bb4ee6a4SAndroid Build Coastguard Worker }
882*bb4ee6a4SAndroid Build Coastguard Worker 
883*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64 + 'static> IrqChipX86_64 for UserspaceIrqChip<V> {
try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>884*bb4ee6a4SAndroid Build Coastguard Worker     fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> {
885*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(self.try_clone()?))
886*bb4ee6a4SAndroid Build Coastguard Worker     }
887*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip(&self) -> &dyn IrqChip888*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip(&self) -> &dyn IrqChip {
889*bb4ee6a4SAndroid Build Coastguard Worker         self
890*bb4ee6a4SAndroid Build Coastguard Worker     }
891*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip_mut(&mut self) -> &mut dyn IrqChip892*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
893*bb4ee6a4SAndroid Build Coastguard Worker         self
894*bb4ee6a4SAndroid Build Coastguard Worker     }
895*bb4ee6a4SAndroid Build Coastguard Worker 
get_pic_state(&self, select: PicSelect) -> Result<PicState>896*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pic_state(&self, select: PicSelect) -> Result<PicState> {
897*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.pic.lock().get_pic_state(select))
898*bb4ee6a4SAndroid Build Coastguard Worker     }
899*bb4ee6a4SAndroid Build Coastguard Worker 
set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>900*bb4ee6a4SAndroid Build Coastguard Worker     fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> {
901*bb4ee6a4SAndroid Build Coastguard Worker         self.pic.lock().set_pic_state(select, state);
902*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
903*bb4ee6a4SAndroid Build Coastguard Worker     }
904*bb4ee6a4SAndroid Build Coastguard Worker 
get_ioapic_state(&self) -> Result<IoapicState>905*bb4ee6a4SAndroid Build Coastguard Worker     fn get_ioapic_state(&self) -> Result<IoapicState> {
906*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.ioapic.lock().get_ioapic_state())
907*bb4ee6a4SAndroid Build Coastguard Worker     }
908*bb4ee6a4SAndroid Build Coastguard Worker 
set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>909*bb4ee6a4SAndroid Build Coastguard Worker     fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> {
910*bb4ee6a4SAndroid Build Coastguard Worker         self.ioapic.lock().set_ioapic_state(state);
911*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
912*bb4ee6a4SAndroid Build Coastguard Worker     }
913*bb4ee6a4SAndroid Build Coastguard Worker 
get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>914*bb4ee6a4SAndroid Build Coastguard Worker     fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> {
915*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.apics[vcpu_id].lock().get_state())
916*bb4ee6a4SAndroid Build Coastguard Worker     }
917*bb4ee6a4SAndroid Build Coastguard Worker 
set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>918*bb4ee6a4SAndroid Build Coastguard Worker     fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> {
919*bb4ee6a4SAndroid Build Coastguard Worker         self.apics[vcpu_id].lock().set_state(state);
920*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
921*bb4ee6a4SAndroid Build Coastguard Worker     }
922*bb4ee6a4SAndroid Build Coastguard Worker 
923*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the lapic frequency in Hz
lapic_frequency(&self) -> u32924*bb4ee6a4SAndroid Build Coastguard Worker     fn lapic_frequency(&self) -> u32 {
925*bb4ee6a4SAndroid Build Coastguard Worker         Apic::frequency()
926*bb4ee6a4SAndroid Build Coastguard Worker     }
927*bb4ee6a4SAndroid Build Coastguard Worker 
get_pit(&self) -> Result<PitState>928*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pit(&self) -> Result<PitState> {
929*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.pit.lock().get_pit_state())
930*bb4ee6a4SAndroid Build Coastguard Worker     }
931*bb4ee6a4SAndroid Build Coastguard Worker 
set_pit(&mut self, state: &PitState) -> Result<()>932*bb4ee6a4SAndroid Build Coastguard Worker     fn set_pit(&mut self, state: &PitState) -> Result<()> {
933*bb4ee6a4SAndroid Build Coastguard Worker         self.pit.lock().set_pit_state(state);
934*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
935*bb4ee6a4SAndroid Build Coastguard Worker     }
936*bb4ee6a4SAndroid Build Coastguard Worker 
937*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused.
938*bb4ee6a4SAndroid Build Coastguard Worker     /// devices::Pit uses 0x61.
pit_uses_speaker_port(&self) -> bool939*bb4ee6a4SAndroid Build Coastguard Worker     fn pit_uses_speaker_port(&self) -> bool {
940*bb4ee6a4SAndroid Build Coastguard Worker         true
941*bb4ee6a4SAndroid Build Coastguard Worker     }
942*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value>943*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value> {
944*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow::anyhow!("Not supported yet in userspace"))
945*bb4ee6a4SAndroid Build Coastguard Worker     }
restore_chip_specific(&mut self, _data: serde_json::Value) -> anyhow::Result<()>946*bb4ee6a4SAndroid Build Coastguard Worker     fn restore_chip_specific(&mut self, _data: serde_json::Value) -> anyhow::Result<()> {
947*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow::anyhow!("Not supported yet in userspace"))
948*bb4ee6a4SAndroid Build Coastguard Worker     }
949*bb4ee6a4SAndroid Build Coastguard Worker }
950*bb4ee6a4SAndroid Build Coastguard Worker 
951*bb4ee6a4SAndroid Build Coastguard Worker /// Condition variable used by `UserspaceIrqChip::wait_until_runnable`.
952*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
953*bb4ee6a4SAndroid Build Coastguard Worker struct Waiter {
954*bb4ee6a4SAndroid Build Coastguard Worker     // mtx stores an "interrupted" bool that's true if `kick_halted_vcpus` has been called.
955*bb4ee6a4SAndroid Build Coastguard Worker     mtx: Mutex<bool>,
956*bb4ee6a4SAndroid Build Coastguard Worker     cvar: Condvar,
957*bb4ee6a4SAndroid Build Coastguard Worker }
958*bb4ee6a4SAndroid Build Coastguard Worker 
959*bb4ee6a4SAndroid Build Coastguard Worker impl Waiter {
960*bb4ee6a4SAndroid Build Coastguard Worker     /// Wakes up `wait_until_runnable` to recheck the interrupted flag and vcpu runnable state.
notify(&self)961*bb4ee6a4SAndroid Build Coastguard Worker     pub fn notify(&self) {
962*bb4ee6a4SAndroid Build Coastguard Worker         let _lock = self.mtx.lock();
963*bb4ee6a4SAndroid Build Coastguard Worker         self.cvar.notify_all();
964*bb4ee6a4SAndroid Build Coastguard Worker     }
965*bb4ee6a4SAndroid Build Coastguard Worker 
966*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the interrupted flag, and wakes up `wait_until_runnable` to recheck the interrupted
967*bb4ee6a4SAndroid Build Coastguard Worker     /// flag and vcpu runnable state.  If `interrupted` is true, then `wait_until_runnable` should
968*bb4ee6a4SAndroid Build Coastguard Worker     /// stop waiting for a runnable vcpu and return immediately.
set_and_notify(&self, interrupted: bool)969*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_and_notify(&self, interrupted: bool) {
970*bb4ee6a4SAndroid Build Coastguard Worker         let mut interrupted_lock = self.mtx.lock();
971*bb4ee6a4SAndroid Build Coastguard Worker         *interrupted_lock = interrupted;
972*bb4ee6a4SAndroid Build Coastguard Worker         self.cvar.notify_all();
973*bb4ee6a4SAndroid Build Coastguard Worker     }
974*bb4ee6a4SAndroid Build Coastguard Worker }
975*bb4ee6a4SAndroid Build Coastguard Worker 
976*bb4ee6a4SAndroid Build Coastguard Worker /// Worker thread for polling timer events and sending them to an APIC.
977*bb4ee6a4SAndroid Build Coastguard Worker struct TimerWorker<V: VcpuX86_64> {
978*bb4ee6a4SAndroid Build Coastguard Worker     id: usize,
979*bb4ee6a4SAndroid Build Coastguard Worker     apic: Arc<Mutex<Apic>>,
980*bb4ee6a4SAndroid Build Coastguard Worker     vcpus: Arc<Mutex<Vec<Option<V>>>>,
981*bb4ee6a4SAndroid Build Coastguard Worker     descriptor: Descriptor,
982*bb4ee6a4SAndroid Build Coastguard Worker     waiter: Arc<Waiter>,
983*bb4ee6a4SAndroid Build Coastguard Worker }
984*bb4ee6a4SAndroid Build Coastguard Worker 
985*bb4ee6a4SAndroid Build Coastguard Worker impl<V: VcpuX86_64> TimerWorker<V> {
run(&mut self, kill_evt: Event) -> TimerWorkerResult<()>986*bb4ee6a4SAndroid Build Coastguard Worker     fn run(&mut self, kill_evt: Event) -> TimerWorkerResult<()> {
987*bb4ee6a4SAndroid Build Coastguard Worker         #[derive(EventToken)]
988*bb4ee6a4SAndroid Build Coastguard Worker         enum Token {
989*bb4ee6a4SAndroid Build Coastguard Worker             // The timer expired.
990*bb4ee6a4SAndroid Build Coastguard Worker             TimerExpire,
991*bb4ee6a4SAndroid Build Coastguard Worker             // The parent thread requested an exit.
992*bb4ee6a4SAndroid Build Coastguard Worker             Kill,
993*bb4ee6a4SAndroid Build Coastguard Worker         }
994*bb4ee6a4SAndroid Build Coastguard Worker 
995*bb4ee6a4SAndroid Build Coastguard Worker         let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
996*bb4ee6a4SAndroid Build Coastguard Worker             (&self.descriptor, Token::TimerExpire),
997*bb4ee6a4SAndroid Build Coastguard Worker             (&kill_evt, Token::Kill),
998*bb4ee6a4SAndroid Build Coastguard Worker         ])
999*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(TimerWorkerError::CreateWaitContext)?;
1000*bb4ee6a4SAndroid Build Coastguard Worker 
1001*bb4ee6a4SAndroid Build Coastguard Worker         loop {
1002*bb4ee6a4SAndroid Build Coastguard Worker             let events = wait_ctx.wait().map_err(TimerWorkerError::WaitError)?;
1003*bb4ee6a4SAndroid Build Coastguard Worker             for event in events.iter().filter(|e| e.is_readable) {
1004*bb4ee6a4SAndroid Build Coastguard Worker                 match event.token {
1005*bb4ee6a4SAndroid Build Coastguard Worker                     Token::TimerExpire => {
1006*bb4ee6a4SAndroid Build Coastguard Worker                         self.apic.lock().handle_timer_expiration();
1007*bb4ee6a4SAndroid Build Coastguard Worker                         if let Some(Some(vcpu)) = self.vcpus.lock().get(self.id) {
1008*bb4ee6a4SAndroid Build Coastguard Worker                             vcpu.set_interrupt_window_requested(true);
1009*bb4ee6a4SAndroid Build Coastguard Worker                         }
1010*bb4ee6a4SAndroid Build Coastguard Worker                         self.waiter.notify();
1011*bb4ee6a4SAndroid Build Coastguard Worker                     }
1012*bb4ee6a4SAndroid Build Coastguard Worker                     Token::Kill => return Ok(()),
1013*bb4ee6a4SAndroid Build Coastguard Worker                 }
1014*bb4ee6a4SAndroid Build Coastguard Worker             }
1015*bb4ee6a4SAndroid Build Coastguard Worker         }
1016*bb4ee6a4SAndroid Build Coastguard Worker     }
1017*bb4ee6a4SAndroid Build Coastguard Worker }
1018*bb4ee6a4SAndroid Build Coastguard Worker 
1019*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
1020*bb4ee6a4SAndroid Build Coastguard Worker enum TimerWorkerError {
1021*bb4ee6a4SAndroid Build Coastguard Worker     /// Creating WaitContext failed.
1022*bb4ee6a4SAndroid Build Coastguard Worker     CreateWaitContext(Error),
1023*bb4ee6a4SAndroid Build Coastguard Worker     /// Error while waiting for events.
1024*bb4ee6a4SAndroid Build Coastguard Worker     WaitError(Error),
1025*bb4ee6a4SAndroid Build Coastguard Worker }
1026*bb4ee6a4SAndroid Build Coastguard Worker 
1027*bb4ee6a4SAndroid Build Coastguard Worker impl Display for TimerWorkerError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1028*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1029*bb4ee6a4SAndroid Build Coastguard Worker         use self::TimerWorkerError::*;
1030*bb4ee6a4SAndroid Build Coastguard Worker 
1031*bb4ee6a4SAndroid Build Coastguard Worker         match self {
1032*bb4ee6a4SAndroid Build Coastguard Worker             CreateWaitContext(e) => write!(f, "failed to create event context: {}", e),
1033*bb4ee6a4SAndroid Build Coastguard Worker             WaitError(e) => write!(f, "failed to wait for events: {}", e),
1034*bb4ee6a4SAndroid Build Coastguard Worker         }
1035*bb4ee6a4SAndroid Build Coastguard Worker     }
1036*bb4ee6a4SAndroid Build Coastguard Worker }
1037*bb4ee6a4SAndroid Build Coastguard Worker 
1038*bb4ee6a4SAndroid Build Coastguard Worker impl std::error::Error for TimerWorkerError {}
1039*bb4ee6a4SAndroid Build Coastguard Worker 
1040*bb4ee6a4SAndroid Build Coastguard Worker type TimerWorkerResult<T> = std::result::Result<T, TimerWorkerError>;
1041