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(®s)?; 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