1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2021 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::sync::Arc; 7*bb4ee6a4SAndroid Build Coastguard Worker 8*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context; 9*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize; 10*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize; 11*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex; 12*bb4ee6a4SAndroid Build Coastguard Worker 13*bb4ee6a4SAndroid Build Coastguard Worker cfg_if::cfg_if! { 14*bb4ee6a4SAndroid Build Coastguard Worker if #[cfg(test)] { 15*bb4ee6a4SAndroid Build Coastguard Worker use base::FakeClock as Clock; 16*bb4ee6a4SAndroid Build Coastguard Worker } else { 17*bb4ee6a4SAndroid Build Coastguard Worker use base::Clock; 18*bb4ee6a4SAndroid Build Coastguard Worker } 19*bb4ee6a4SAndroid Build Coastguard Worker } 20*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 21*bb4ee6a4SAndroid Build Coastguard Worker use base::Error; 22*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 23*bb4ee6a4SAndroid Build Coastguard Worker use base::Result; 24*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube; 25*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxVcpu; 26*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::whpx::WhpxVm; 27*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoapicState; 28*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute; 29*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSource; 30*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSourceChip; 31*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::LapicState; 32*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MPState; 33*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MsiAddressMessage; 34*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MsiDataMessage; 35*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicSelect; 36*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicState; 37*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PitState; 38*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vcpu; 39*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VcpuX86_64; 40*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm; 41*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator; 42*bb4ee6a4SAndroid Build Coastguard Worker 43*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::DelayedIoApicIrqEvents; 44*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::InterruptData; 45*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::InterruptDestination; 46*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Ioapic; 47*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IrqEvent; 48*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IrqEventIndex; 49*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Pic; 50*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::Routes; 51*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::VcpuRunState; 52*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IOAPIC_BASE_ADDRESS; 53*bb4ee6a4SAndroid Build Coastguard Worker use crate::irqchip::IOAPIC_MEM_LENGTH_BYTES; 54*bb4ee6a4SAndroid Build Coastguard Worker use crate::Bus; 55*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip; 56*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipCap; 57*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipX86_64; 58*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEdgeEvent; 59*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventSource; 60*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent; 61*bb4ee6a4SAndroid Build Coastguard Worker use crate::Pit; 62*bb4ee6a4SAndroid Build Coastguard Worker use crate::PitError; 63*bb4ee6a4SAndroid Build Coastguard Worker 64*bb4ee6a4SAndroid Build Coastguard Worker /// PIT channel 0 timer is connected to IRQ 0 65*bb4ee6a4SAndroid Build Coastguard Worker const PIT_CHANNEL0_IRQ: u32 = 0; 66*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/187464379): we don't know what the right frequency is here, but 100MHz gives 67*bb4ee6a4SAndroid Build Coastguard Worker /// us better results than the frequency that WSL seems to use, which is 500MHz. 68*bb4ee6a4SAndroid Build Coastguard Worker const WHPX_LOCAL_APIC_EMULATION_APIC_FREQUENCY: u32 = 100_000_000; 69*bb4ee6a4SAndroid Build Coastguard Worker 70*bb4ee6a4SAndroid Build Coastguard Worker /// The WhpxSplitIrqChip supports 71*bb4ee6a4SAndroid Build Coastguard Worker pub struct WhpxSplitIrqChip { 72*bb4ee6a4SAndroid Build Coastguard Worker vm: WhpxVm, 73*bb4ee6a4SAndroid Build Coastguard Worker routes: Arc<Mutex<Routes>>, 74*bb4ee6a4SAndroid Build Coastguard Worker pit: Arc<Mutex<Pit>>, 75*bb4ee6a4SAndroid Build Coastguard Worker pic: Arc<Mutex<Pic>>, 76*bb4ee6a4SAndroid Build Coastguard Worker ioapic: Arc<Mutex<Ioapic>>, 77*bb4ee6a4SAndroid Build Coastguard Worker ioapic_pins: usize, 78*bb4ee6a4SAndroid Build Coastguard Worker /// Delayed ioapic irq object, that contains the delayed events because the ioapic was locked 79*bb4ee6a4SAndroid Build Coastguard Worker /// when service_irq was called on the irqchip. This prevents deadlocks when a Vcpu thread has 80*bb4ee6a4SAndroid Build Coastguard Worker /// locked the ioapic and the ioapic sends a AddMsiRoute signal to the main thread (which 81*bb4ee6a4SAndroid Build Coastguard Worker /// itself may be busy trying to call service_irq). 82*bb4ee6a4SAndroid Build Coastguard Worker /// 83*bb4ee6a4SAndroid Build Coastguard Worker /// ## Note: 84*bb4ee6a4SAndroid Build Coastguard Worker /// This lock may be locked by itself to access the `DelayedIoApicIrqEvents`. If accessed in 85*bb4ee6a4SAndroid Build Coastguard Worker /// conjunction with the `irq_events` field, that lock should be taken first to prevent 86*bb4ee6a4SAndroid Build Coastguard Worker /// deadlocks stemming from lock-ordering issues. 87*bb4ee6a4SAndroid Build Coastguard Worker delayed_ioapic_irq_events: Arc<Mutex<DelayedIoApicIrqEvents>>, 88*bb4ee6a4SAndroid Build Coastguard Worker /// Array of Events that devices will use to assert ioapic pins. 89*bb4ee6a4SAndroid Build Coastguard Worker irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>, 90*bb4ee6a4SAndroid Build Coastguard Worker } 91*bb4ee6a4SAndroid Build Coastguard Worker 92*bb4ee6a4SAndroid Build Coastguard Worker impl WhpxSplitIrqChip { 93*bb4ee6a4SAndroid Build Coastguard Worker /// Construct a new WhpxSplitIrqChip. new(vm: WhpxVm, irq_tube: Tube, ioapic_pins: Option<usize>) -> Result<Self>94*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(vm: WhpxVm, irq_tube: Tube, ioapic_pins: Option<usize>) -> Result<Self> { 95*bb4ee6a4SAndroid Build Coastguard Worker let pit_evt = IrqEdgeEvent::new()?; 96*bb4ee6a4SAndroid Build Coastguard Worker let pit = Pit::new(pit_evt.try_clone()?, Arc::new(Mutex::new(Clock::new()))).map_err( 97*bb4ee6a4SAndroid Build Coastguard Worker |e| match e { 98*bb4ee6a4SAndroid Build Coastguard Worker PitError::CloneEvent(err) => err, 99*bb4ee6a4SAndroid Build Coastguard Worker PitError::CreateEvent(err) => err, 100*bb4ee6a4SAndroid Build Coastguard Worker PitError::CreateWaitContext(err) => err, 101*bb4ee6a4SAndroid Build Coastguard Worker PitError::WaitError(err) => err, 102*bb4ee6a4SAndroid Build Coastguard Worker PitError::TimerCreateError(err) => err, 103*bb4ee6a4SAndroid Build Coastguard Worker PitError::SpawnThread(_) => Error::new(libc::EIO), 104*bb4ee6a4SAndroid Build Coastguard Worker }, 105*bb4ee6a4SAndroid Build Coastguard Worker )?; 106*bb4ee6a4SAndroid Build Coastguard Worker 107*bb4ee6a4SAndroid Build Coastguard Worker let pit_event_source = IrqEventSource::from_device(&pit); 108*bb4ee6a4SAndroid Build Coastguard Worker 109*bb4ee6a4SAndroid Build Coastguard Worker let ioapic_pins = ioapic_pins.unwrap_or(hypervisor::NUM_IOAPIC_PINS); 110*bb4ee6a4SAndroid Build Coastguard Worker let ioapic = Ioapic::new(irq_tube, ioapic_pins)?; 111*bb4ee6a4SAndroid Build Coastguard Worker 112*bb4ee6a4SAndroid Build Coastguard Worker let mut chip = WhpxSplitIrqChip { 113*bb4ee6a4SAndroid Build Coastguard Worker vm, 114*bb4ee6a4SAndroid Build Coastguard Worker routes: Arc::new(Mutex::new(Routes::new())), 115*bb4ee6a4SAndroid Build Coastguard Worker pit: Arc::new(Mutex::new(pit)), 116*bb4ee6a4SAndroid Build Coastguard Worker pic: Arc::new(Mutex::new(Pic::new())), 117*bb4ee6a4SAndroid Build Coastguard Worker ioapic: Arc::new(Mutex::new(ioapic)), 118*bb4ee6a4SAndroid Build Coastguard Worker ioapic_pins, 119*bb4ee6a4SAndroid Build Coastguard Worker delayed_ioapic_irq_events: Arc::new(Mutex::new(DelayedIoApicIrqEvents::new()?)), 120*bb4ee6a4SAndroid Build Coastguard Worker irq_events: Arc::new(Mutex::new(Vec::new())), 121*bb4ee6a4SAndroid Build Coastguard Worker }; 122*bb4ee6a4SAndroid Build Coastguard Worker 123*bb4ee6a4SAndroid Build Coastguard Worker // This is equivalent to setting this in the blank Routes object above because 124*bb4ee6a4SAndroid Build Coastguard Worker // WhpxSplitIrqChip doesn't interact with the WHPX API when setting routes, but in case 125*bb4ee6a4SAndroid Build Coastguard Worker // that changes we do it this way. 126*bb4ee6a4SAndroid Build Coastguard Worker chip.set_irq_routes(&Routes::default_pic_ioapic_routes(ioapic_pins))?; 127*bb4ee6a4SAndroid Build Coastguard Worker 128*bb4ee6a4SAndroid Build Coastguard Worker // Add the pit 129*bb4ee6a4SAndroid Build Coastguard Worker chip.register_edge_irq_event(PIT_CHANNEL0_IRQ, &pit_evt, pit_event_source)?; 130*bb4ee6a4SAndroid Build Coastguard Worker Ok(chip) 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker 133*bb4ee6a4SAndroid Build Coastguard Worker /// Sends a Message Signaled Interrupt to one or more APICs. The WHPX API does not accept the 134*bb4ee6a4SAndroid Build Coastguard Worker /// MSI address and data directly, so we must parse them and supply WHPX with the vector, 135*bb4ee6a4SAndroid Build Coastguard Worker /// destination id, destination mode, trigger mode, and delivery mode (aka interrupt type). send_msi(&self, addr: u32, data: u32) -> Result<()>136*bb4ee6a4SAndroid Build Coastguard Worker fn send_msi(&self, addr: u32, data: u32) -> Result<()> { 137*bb4ee6a4SAndroid Build Coastguard Worker let mut msi_addr = MsiAddressMessage::new(); 138*bb4ee6a4SAndroid Build Coastguard Worker msi_addr.set(0, 32, addr as u64); 139*bb4ee6a4SAndroid Build Coastguard Worker let dest = InterruptDestination::try_from(&msi_addr).or(Err(Error::new(libc::EINVAL)))?; 140*bb4ee6a4SAndroid Build Coastguard Worker 141*bb4ee6a4SAndroid Build Coastguard Worker let mut msi_data = MsiDataMessage::new(); 142*bb4ee6a4SAndroid Build Coastguard Worker msi_data.set(0, 32, data as u64); 143*bb4ee6a4SAndroid Build Coastguard Worker let data = InterruptData::from(&msi_data); 144*bb4ee6a4SAndroid Build Coastguard Worker 145*bb4ee6a4SAndroid Build Coastguard Worker self.vm.request_interrupt( 146*bb4ee6a4SAndroid Build Coastguard Worker data.vector, 147*bb4ee6a4SAndroid Build Coastguard Worker dest.dest_id, 148*bb4ee6a4SAndroid Build Coastguard Worker dest.mode, 149*bb4ee6a4SAndroid Build Coastguard Worker data.trigger, 150*bb4ee6a4SAndroid Build Coastguard Worker data.delivery, 151*bb4ee6a4SAndroid Build Coastguard Worker ) 152*bb4ee6a4SAndroid Build Coastguard Worker } 153*bb4ee6a4SAndroid Build Coastguard Worker 154*bb4ee6a4SAndroid Build Coastguard Worker /// Return true if there is a pending interrupt for the specified vcpu. For WhpxSplitIrqChip 155*bb4ee6a4SAndroid Build Coastguard Worker /// this calls interrupt_requested on the pic. interrupt_requested(&self, vcpu_id: usize) -> bool156*bb4ee6a4SAndroid Build Coastguard Worker pub fn interrupt_requested(&self, vcpu_id: usize) -> bool { 157*bb4ee6a4SAndroid Build Coastguard Worker // Pic interrupts for the split irqchip only go to vcpu 0 158*bb4ee6a4SAndroid Build Coastguard Worker if vcpu_id != 0 { 159*bb4ee6a4SAndroid Build Coastguard Worker return false; 160*bb4ee6a4SAndroid Build Coastguard Worker } 161*bb4ee6a4SAndroid Build Coastguard Worker self.pic.lock().interrupt_requested() 162*bb4ee6a4SAndroid Build Coastguard Worker } 163*bb4ee6a4SAndroid Build Coastguard Worker 164*bb4ee6a4SAndroid Build Coastguard Worker /// Check if the specified vcpu has any pending interrupts. Returns [`None`] for no interrupts, 165*bb4ee6a4SAndroid Build Coastguard Worker /// otherwise [`Some::<u8>`] should be the injected interrupt vector. For [`WhpxSplitIrqChip`] 166*bb4ee6a4SAndroid Build Coastguard Worker /// this calls `get_external_interrupt` on the pic. get_external_interrupt(&self, vcpu_id: usize) -> Result<Option<u8>>167*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_external_interrupt(&self, vcpu_id: usize) -> Result<Option<u8>> { 168*bb4ee6a4SAndroid Build Coastguard Worker // Pic interrupts for the split irqchip only go to vcpu 0 169*bb4ee6a4SAndroid Build Coastguard Worker if vcpu_id != 0 { 170*bb4ee6a4SAndroid Build Coastguard Worker return Ok(None); 171*bb4ee6a4SAndroid Build Coastguard Worker } 172*bb4ee6a4SAndroid Build Coastguard Worker if let Some(vector) = self.pic.lock().get_external_interrupt() { 173*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some(vector)) 174*bb4ee6a4SAndroid Build Coastguard Worker } else { 175*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 176*bb4ee6a4SAndroid Build Coastguard Worker } 177*bb4ee6a4SAndroid Build Coastguard Worker } 178*bb4ee6a4SAndroid Build Coastguard Worker } 179*bb4ee6a4SAndroid Build Coastguard Worker 180*bb4ee6a4SAndroid Build Coastguard Worker impl WhpxSplitIrqChip { register_irq_event( &mut self, irq: u32, irq_event: &Event, resample_event: Option<&Event>, source: IrqEventSource, ) -> Result<Option<usize>>181*bb4ee6a4SAndroid Build Coastguard Worker fn register_irq_event( 182*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 183*bb4ee6a4SAndroid Build Coastguard Worker irq: u32, 184*bb4ee6a4SAndroid Build Coastguard Worker irq_event: &Event, 185*bb4ee6a4SAndroid Build Coastguard Worker resample_event: Option<&Event>, 186*bb4ee6a4SAndroid Build Coastguard Worker source: IrqEventSource, 187*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<usize>> { 188*bb4ee6a4SAndroid Build Coastguard Worker let mut evt = IrqEvent { 189*bb4ee6a4SAndroid Build Coastguard Worker gsi: irq, 190*bb4ee6a4SAndroid Build Coastguard Worker event: irq_event.try_clone()?, 191*bb4ee6a4SAndroid Build Coastguard Worker resample_event: None, 192*bb4ee6a4SAndroid Build Coastguard Worker source, 193*bb4ee6a4SAndroid Build Coastguard Worker }; 194*bb4ee6a4SAndroid Build Coastguard Worker 195*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_event) = resample_event { 196*bb4ee6a4SAndroid Build Coastguard Worker evt.resample_event = Some(resample_event.try_clone()?); 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker 199*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_events = self.irq_events.lock(); 200*bb4ee6a4SAndroid Build Coastguard Worker let index = irq_events.len(); 201*bb4ee6a4SAndroid Build Coastguard Worker irq_events.push(Some(evt)); 202*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some(index)) 203*bb4ee6a4SAndroid Build Coastguard Worker } 204*bb4ee6a4SAndroid Build Coastguard Worker unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()>205*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()> { 206*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_events = self.irq_events.lock(); 207*bb4ee6a4SAndroid Build Coastguard Worker for (index, evt) in irq_events.iter().enumerate() { 208*bb4ee6a4SAndroid Build Coastguard Worker if let Some(evt) = evt { 209*bb4ee6a4SAndroid Build Coastguard Worker if evt.gsi == irq && irq_event.eq(&evt.event) { 210*bb4ee6a4SAndroid Build Coastguard Worker irq_events[index] = None; 211*bb4ee6a4SAndroid Build Coastguard Worker break; 212*bb4ee6a4SAndroid Build Coastguard Worker } 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker } 215*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 216*bb4ee6a4SAndroid Build Coastguard Worker } 217*bb4ee6a4SAndroid Build Coastguard Worker } 218*bb4ee6a4SAndroid Build Coastguard Worker 219*bb4ee6a4SAndroid Build Coastguard Worker /// This IrqChip only works with Whpx so we only implement it for WhpxVcpu. 220*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChip for WhpxSplitIrqChip { add_vcpu(&mut self, _vcpu_id: usize, _vcpu: &dyn Vcpu) -> Result<()>221*bb4ee6a4SAndroid Build Coastguard Worker fn add_vcpu(&mut self, _vcpu_id: usize, _vcpu: &dyn Vcpu) -> Result<()> { 222*bb4ee6a4SAndroid Build Coastguard Worker // The WHPX API acts entirely on the VM partition, so we don't need to keep references to 223*bb4ee6a4SAndroid Build Coastguard Worker // the vcpus. 224*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 225*bb4ee6a4SAndroid Build Coastguard Worker } 226*bb4ee6a4SAndroid Build Coastguard Worker register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>227*bb4ee6a4SAndroid Build Coastguard Worker fn register_edge_irq_event( 228*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 229*bb4ee6a4SAndroid Build Coastguard Worker irq: u32, 230*bb4ee6a4SAndroid Build Coastguard Worker irq_event: &IrqEdgeEvent, 231*bb4ee6a4SAndroid Build Coastguard Worker source: IrqEventSource, 232*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<IrqEventIndex>> { 233*bb4ee6a4SAndroid Build Coastguard Worker self.register_irq_event(irq, irq_event.get_trigger(), None, source) 234*bb4ee6a4SAndroid Build Coastguard Worker } 235*bb4ee6a4SAndroid Build Coastguard Worker unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>236*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> { 237*bb4ee6a4SAndroid Build Coastguard Worker self.unregister_irq_event(irq, irq_event.get_trigger()) 238*bb4ee6a4SAndroid Build Coastguard Worker } 239*bb4ee6a4SAndroid Build Coastguard Worker register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>240*bb4ee6a4SAndroid Build Coastguard Worker fn register_level_irq_event( 241*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 242*bb4ee6a4SAndroid Build Coastguard Worker irq: u32, 243*bb4ee6a4SAndroid Build Coastguard Worker irq_event: &IrqLevelEvent, 244*bb4ee6a4SAndroid Build Coastguard Worker source: IrqEventSource, 245*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<IrqEventIndex>> { 246*bb4ee6a4SAndroid Build Coastguard Worker self.register_irq_event( 247*bb4ee6a4SAndroid Build Coastguard Worker irq, 248*bb4ee6a4SAndroid Build Coastguard Worker irq_event.get_trigger(), 249*bb4ee6a4SAndroid Build Coastguard Worker Some(irq_event.get_resample()), 250*bb4ee6a4SAndroid Build Coastguard Worker source, 251*bb4ee6a4SAndroid Build Coastguard Worker ) 252*bb4ee6a4SAndroid Build Coastguard Worker } 253*bb4ee6a4SAndroid Build Coastguard Worker unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>254*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> { 255*bb4ee6a4SAndroid Build Coastguard Worker self.unregister_irq_event(irq, irq_event.get_trigger()) 256*bb4ee6a4SAndroid Build Coastguard Worker } 257*bb4ee6a4SAndroid Build Coastguard Worker route_irq(&mut self, route: IrqRoute) -> Result<()>258*bb4ee6a4SAndroid Build Coastguard Worker fn route_irq(&mut self, route: IrqRoute) -> Result<()> { 259*bb4ee6a4SAndroid Build Coastguard Worker self.routes.lock().add(route) 260*bb4ee6a4SAndroid Build Coastguard Worker } 261*bb4ee6a4SAndroid Build Coastguard Worker set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>262*bb4ee6a4SAndroid Build Coastguard Worker fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()> { 263*bb4ee6a4SAndroid Build Coastguard Worker self.routes.lock().replace_all(routes) 264*bb4ee6a4SAndroid Build Coastguard Worker } 265*bb4ee6a4SAndroid Build Coastguard Worker irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>266*bb4ee6a4SAndroid Build Coastguard Worker fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> { 267*bb4ee6a4SAndroid Build Coastguard Worker let mut tokens: Vec<(IrqEventIndex, IrqEventSource, Event)> = Vec::new(); 268*bb4ee6a4SAndroid Build Coastguard Worker for (index, evt) in self.irq_events.lock().iter().enumerate() { 269*bb4ee6a4SAndroid Build Coastguard Worker if let Some(evt) = evt { 270*bb4ee6a4SAndroid Build Coastguard Worker tokens.push((index, evt.source.clone(), evt.event.try_clone()?)); 271*bb4ee6a4SAndroid Build Coastguard Worker } 272*bb4ee6a4SAndroid Build Coastguard Worker } 273*bb4ee6a4SAndroid Build Coastguard Worker Ok(tokens) 274*bb4ee6a4SAndroid Build Coastguard Worker } 275*bb4ee6a4SAndroid Build Coastguard Worker service_irq(&mut self, irq: u32, level: bool) -> Result<()>276*bb4ee6a4SAndroid Build Coastguard Worker fn service_irq(&mut self, irq: u32, level: bool) -> Result<()> { 277*bb4ee6a4SAndroid Build Coastguard Worker for route in self.routes.lock()[irq as usize].iter() { 278*bb4ee6a4SAndroid Build Coastguard Worker match *route { 279*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Irqchip { 280*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::PicPrimary, 281*bb4ee6a4SAndroid Build Coastguard Worker pin, 282*bb4ee6a4SAndroid Build Coastguard Worker } 283*bb4ee6a4SAndroid Build Coastguard Worker | IrqSource::Irqchip { 284*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::PicSecondary, 285*bb4ee6a4SAndroid Build Coastguard Worker pin, 286*bb4ee6a4SAndroid Build Coastguard Worker } => { 287*bb4ee6a4SAndroid Build Coastguard Worker self.pic.lock().service_irq(pin as u8, level); 288*bb4ee6a4SAndroid Build Coastguard Worker } 289*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Irqchip { 290*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::Ioapic, 291*bb4ee6a4SAndroid Build Coastguard Worker pin, 292*bb4ee6a4SAndroid Build Coastguard Worker } => { 293*bb4ee6a4SAndroid Build Coastguard Worker self.ioapic.lock().service_irq(pin as usize, level); 294*bb4ee6a4SAndroid Build Coastguard Worker } 295*bb4ee6a4SAndroid Build Coastguard Worker // service_irq's level parameter is ignored for MSIs. MSI data specifies the level. 296*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Msi { address, data } => self.send_msi(address as u32, data)?, 297*bb4ee6a4SAndroid Build Coastguard Worker _ => { 298*bb4ee6a4SAndroid Build Coastguard Worker error!("Unexpected route source {:?}", route); 299*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EINVAL)); 300*bb4ee6a4SAndroid Build Coastguard Worker } 301*bb4ee6a4SAndroid Build Coastguard Worker } 302*bb4ee6a4SAndroid Build Coastguard Worker } 303*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 304*bb4ee6a4SAndroid Build Coastguard Worker } 305*bb4ee6a4SAndroid Build Coastguard Worker 306*bb4ee6a4SAndroid Build Coastguard Worker /// Services an IRQ event by asserting then deasserting an IRQ line. The associated Event 307*bb4ee6a4SAndroid Build Coastguard Worker /// that triggered the irq event will be read from. If the irq is associated with a resample 308*bb4ee6a4SAndroid Build Coastguard Worker /// Event, then the deassert will only happen after an EOI is broadcast for a vector 309*bb4ee6a4SAndroid Build Coastguard Worker /// associated with the irq line. 310*bb4ee6a4SAndroid Build Coastguard Worker /// For WhpxSplitIrqChip, this function identifies the destination(s) of the irq: PIC, IOAPIC, 311*bb4ee6a4SAndroid Build Coastguard Worker /// or APIC (MSI). If it's a PIC or IOAPIC route, we attempt to call service_irq on those 312*bb4ee6a4SAndroid Build Coastguard Worker /// chips. If the IOAPIC is unable to be immediately locked, we add the irq to the 313*bb4ee6a4SAndroid Build Coastguard Worker /// delayed_ioapic_irq_events (though we still read from the Event that triggered the irq 314*bb4ee6a4SAndroid Build Coastguard Worker /// event). If it's an MSI route, we call send_msi to decode the MSI and send the interrupt 315*bb4ee6a4SAndroid Build Coastguard Worker /// to WHPX. service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>316*bb4ee6a4SAndroid Build Coastguard Worker fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()> { 317*bb4ee6a4SAndroid Build Coastguard Worker let irq_events = self.irq_events.lock(); 318*bb4ee6a4SAndroid Build Coastguard Worker let evt = if let Some(evt) = &irq_events[event_index] { 319*bb4ee6a4SAndroid Build Coastguard Worker evt 320*bb4ee6a4SAndroid Build Coastguard Worker } else { 321*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 322*bb4ee6a4SAndroid Build Coastguard Worker }; 323*bb4ee6a4SAndroid Build Coastguard Worker evt.event.wait()?; 324*bb4ee6a4SAndroid Build Coastguard Worker 325*bb4ee6a4SAndroid Build Coastguard Worker for route in self.routes.lock()[evt.gsi as usize].iter() { 326*bb4ee6a4SAndroid Build Coastguard Worker match *route { 327*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Irqchip { 328*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::PicPrimary, 329*bb4ee6a4SAndroid Build Coastguard Worker pin, 330*bb4ee6a4SAndroid Build Coastguard Worker } 331*bb4ee6a4SAndroid Build Coastguard Worker | IrqSource::Irqchip { 332*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::PicSecondary, 333*bb4ee6a4SAndroid Build Coastguard Worker pin, 334*bb4ee6a4SAndroid Build Coastguard Worker } => { 335*bb4ee6a4SAndroid Build Coastguard Worker let mut pic = self.pic.lock(); 336*bb4ee6a4SAndroid Build Coastguard Worker if evt.resample_event.is_some() { 337*bb4ee6a4SAndroid Build Coastguard Worker pic.service_irq(pin as u8, true); 338*bb4ee6a4SAndroid Build Coastguard Worker } else { 339*bb4ee6a4SAndroid Build Coastguard Worker pic.service_irq(pin as u8, true); 340*bb4ee6a4SAndroid Build Coastguard Worker pic.service_irq(pin as u8, false); 341*bb4ee6a4SAndroid Build Coastguard Worker } 342*bb4ee6a4SAndroid Build Coastguard Worker } 343*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Irqchip { 344*bb4ee6a4SAndroid Build Coastguard Worker chip: IrqSourceChip::Ioapic, 345*bb4ee6a4SAndroid Build Coastguard Worker pin, 346*bb4ee6a4SAndroid Build Coastguard Worker } => { 347*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(mut ioapic) = self.ioapic.try_lock() { 348*bb4ee6a4SAndroid Build Coastguard Worker if evt.resample_event.is_some() { 349*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(pin as usize, true); 350*bb4ee6a4SAndroid Build Coastguard Worker } else { 351*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(pin as usize, true); 352*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(pin as usize, false); 353*bb4ee6a4SAndroid Build Coastguard Worker } 354*bb4ee6a4SAndroid Build Coastguard Worker } else { 355*bb4ee6a4SAndroid Build Coastguard Worker let mut delayed_events = self.delayed_ioapic_irq_events.lock(); 356*bb4ee6a4SAndroid Build Coastguard Worker delayed_events.events.push(event_index); 357*bb4ee6a4SAndroid Build Coastguard Worker delayed_events.trigger.signal()?; 358*bb4ee6a4SAndroid Build Coastguard Worker } 359*bb4ee6a4SAndroid Build Coastguard Worker } 360*bb4ee6a4SAndroid Build Coastguard Worker IrqSource::Msi { address, data } => self.send_msi(address as u32, data)?, 361*bb4ee6a4SAndroid Build Coastguard Worker _ => { 362*bb4ee6a4SAndroid Build Coastguard Worker error!("Unexpected route source {:?}", route); 363*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EINVAL)); 364*bb4ee6a4SAndroid Build Coastguard Worker } 365*bb4ee6a4SAndroid Build Coastguard Worker } 366*bb4ee6a4SAndroid Build Coastguard Worker } 367*bb4ee6a4SAndroid Build Coastguard Worker 368*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 369*bb4ee6a4SAndroid Build Coastguard Worker } 370*bb4ee6a4SAndroid Build Coastguard Worker 371*bb4ee6a4SAndroid Build Coastguard Worker /// Broadcasts an end of interrupt. For WhpxSplitIrqChip this sends the EOI to the Ioapic. broadcast_eoi(&self, vector: u8) -> Result<()>372*bb4ee6a4SAndroid Build Coastguard Worker fn broadcast_eoi(&self, vector: u8) -> Result<()> { 373*bb4ee6a4SAndroid Build Coastguard Worker self.ioapic.lock().end_of_interrupt(vector); 374*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 375*bb4ee6a4SAndroid Build Coastguard Worker } 376*bb4ee6a4SAndroid Build Coastguard Worker 377*bb4ee6a4SAndroid Build Coastguard Worker /// Injects any pending interrupts for `vcpu`. 378*bb4ee6a4SAndroid Build Coastguard Worker /// For WhpxSplitIrqChip this injects any PIC interrupts on vcpu_id 0. inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>379*bb4ee6a4SAndroid Build Coastguard Worker fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()> { 380*bb4ee6a4SAndroid Build Coastguard Worker let vcpu: &WhpxVcpu = vcpu 381*bb4ee6a4SAndroid Build Coastguard Worker .downcast_ref() 382*bb4ee6a4SAndroid Build Coastguard Worker .expect("WhpxSplitIrqChip::add_vcpu called with non-WhpxVcpu"); 383*bb4ee6a4SAndroid Build Coastguard Worker let vcpu_id = vcpu.id(); 384*bb4ee6a4SAndroid Build Coastguard Worker if !self.interrupt_requested(vcpu_id) || !vcpu.ready_for_interrupt() { 385*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 386*bb4ee6a4SAndroid Build Coastguard Worker } 387*bb4ee6a4SAndroid Build Coastguard Worker 388*bb4ee6a4SAndroid Build Coastguard Worker if let Some(vector) = self.get_external_interrupt(vcpu_id)? { 389*bb4ee6a4SAndroid Build Coastguard Worker vcpu.interrupt(vector)?; 390*bb4ee6a4SAndroid Build Coastguard Worker } 391*bb4ee6a4SAndroid Build Coastguard Worker 392*bb4ee6a4SAndroid Build Coastguard Worker // The second interrupt request should be handled immediately, so ask vCPU to exit as soon 393*bb4ee6a4SAndroid Build Coastguard Worker // as possible. 394*bb4ee6a4SAndroid Build Coastguard Worker if self.interrupt_requested(vcpu_id) { 395*bb4ee6a4SAndroid Build Coastguard Worker vcpu.set_interrupt_window_requested(true); 396*bb4ee6a4SAndroid Build Coastguard Worker } 397*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 398*bb4ee6a4SAndroid Build Coastguard Worker } 399*bb4ee6a4SAndroid Build Coastguard Worker 400*bb4ee6a4SAndroid Build Coastguard Worker /// Notifies the irq chip that the specified VCPU has executed a halt instruction. 401*bb4ee6a4SAndroid Build Coastguard Worker /// For WhpxSplitIrqChip this is a no-op because Whpx handles VCPU blocking. halted(&self, _vcpu_id: usize)402*bb4ee6a4SAndroid Build Coastguard Worker fn halted(&self, _vcpu_id: usize) {} 403*bb4ee6a4SAndroid Build Coastguard Worker 404*bb4ee6a4SAndroid Build Coastguard Worker /// Blocks until `vcpu` is in a runnable state or until interrupted by 405*bb4ee6a4SAndroid Build Coastguard Worker /// `IrqChip::kick_halted_vcpus`. Returns `VcpuRunState::Runnable if vcpu is runnable, or 406*bb4ee6a4SAndroid Build Coastguard Worker /// `VcpuRunState::Interrupted` if the wait was interrupted. 407*bb4ee6a4SAndroid Build Coastguard Worker /// For WhpxSplitIrqChip this is a no-op and always returns Runnable because Whpx handles VCPU 408*bb4ee6a4SAndroid Build Coastguard Worker /// blocking. wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>409*bb4ee6a4SAndroid Build Coastguard Worker fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState> { 410*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuRunState::Runnable) 411*bb4ee6a4SAndroid Build Coastguard Worker } 412*bb4ee6a4SAndroid Build Coastguard Worker 413*bb4ee6a4SAndroid Build Coastguard Worker /// Makes unrunnable VCPUs return immediately from `wait_until_runnable`. 414*bb4ee6a4SAndroid Build Coastguard Worker /// For WhpxSplitIrqChip this is a no-op because Whpx handles VCPU blocking. kick_halted_vcpus(&self)415*bb4ee6a4SAndroid Build Coastguard Worker fn kick_halted_vcpus(&self) {} 416*bb4ee6a4SAndroid Build Coastguard Worker get_mp_state(&self, _vcpu_id: usize) -> Result<MPState>417*bb4ee6a4SAndroid Build Coastguard Worker fn get_mp_state(&self, _vcpu_id: usize) -> Result<MPState> { 418*bb4ee6a4SAndroid Build Coastguard Worker // WHPX does not seem to have an API for this, but luckily this API isn't used anywhere 419*bb4ee6a4SAndroid Build Coastguard Worker // except the plugin. 420*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(libc::ENXIO)) 421*bb4ee6a4SAndroid Build Coastguard Worker } 422*bb4ee6a4SAndroid Build Coastguard Worker set_mp_state(&mut self, _vcpu_id: usize, _state: &MPState) -> Result<()>423*bb4ee6a4SAndroid Build Coastguard Worker fn set_mp_state(&mut self, _vcpu_id: usize, _state: &MPState) -> Result<()> { 424*bb4ee6a4SAndroid Build Coastguard Worker // WHPX does not seem to have an API for this, but luckily this API isn't used anywhere 425*bb4ee6a4SAndroid Build Coastguard Worker // except the plugin. 426*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(libc::ENXIO)) 427*bb4ee6a4SAndroid Build Coastguard Worker } 428*bb4ee6a4SAndroid Build Coastguard Worker try_clone(&self) -> Result<Self> where Self: Sized,429*bb4ee6a4SAndroid Build Coastguard Worker fn try_clone(&self) -> Result<Self> 430*bb4ee6a4SAndroid Build Coastguard Worker where 431*bb4ee6a4SAndroid Build Coastguard Worker Self: Sized, 432*bb4ee6a4SAndroid Build Coastguard Worker { 433*bb4ee6a4SAndroid Build Coastguard Worker Ok(WhpxSplitIrqChip { 434*bb4ee6a4SAndroid Build Coastguard Worker vm: self.vm.try_clone()?, 435*bb4ee6a4SAndroid Build Coastguard Worker routes: self.routes.clone(), 436*bb4ee6a4SAndroid Build Coastguard Worker pit: self.pit.clone(), 437*bb4ee6a4SAndroid Build Coastguard Worker pic: self.pic.clone(), 438*bb4ee6a4SAndroid Build Coastguard Worker ioapic: self.ioapic.clone(), 439*bb4ee6a4SAndroid Build Coastguard Worker ioapic_pins: self.ioapic_pins, 440*bb4ee6a4SAndroid Build Coastguard Worker delayed_ioapic_irq_events: self.delayed_ioapic_irq_events.clone(), 441*bb4ee6a4SAndroid Build Coastguard Worker irq_events: self.irq_events.clone(), 442*bb4ee6a4SAndroid Build Coastguard Worker }) 443*bb4ee6a4SAndroid Build Coastguard Worker } 444*bb4ee6a4SAndroid Build Coastguard Worker finalize_devices( &mut self, resources: &mut SystemAllocator, io_bus: &Bus, mmio_bus: &Bus, ) -> Result<()>445*bb4ee6a4SAndroid Build Coastguard Worker fn finalize_devices( 446*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 447*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator, 448*bb4ee6a4SAndroid Build Coastguard Worker io_bus: &Bus, 449*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus: &Bus, 450*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 451*bb4ee6a4SAndroid Build Coastguard Worker // Insert pit into io_bus 452*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(self.pit.clone(), 0x040, 0x8).unwrap(); 453*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(self.pit.clone(), 0x061, 0x1).unwrap(); 454*bb4ee6a4SAndroid Build Coastguard Worker 455*bb4ee6a4SAndroid Build Coastguard Worker // Insert pic into io_bus 456*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(self.pic.clone(), 0x20, 0x2).unwrap(); 457*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(self.pic.clone(), 0xa0, 0x2).unwrap(); 458*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(self.pic.clone(), 0x4d0, 0x2).unwrap(); 459*bb4ee6a4SAndroid Build Coastguard Worker 460*bb4ee6a4SAndroid Build Coastguard Worker // Insert ioapic into mmio_bus 461*bb4ee6a4SAndroid Build Coastguard Worker mmio_bus 462*bb4ee6a4SAndroid Build Coastguard Worker .insert( 463*bb4ee6a4SAndroid Build Coastguard Worker self.ioapic.clone(), 464*bb4ee6a4SAndroid Build Coastguard Worker IOAPIC_BASE_ADDRESS, 465*bb4ee6a4SAndroid Build Coastguard Worker IOAPIC_MEM_LENGTH_BYTES, 466*bb4ee6a4SAndroid Build Coastguard Worker ) 467*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 468*bb4ee6a4SAndroid Build Coastguard Worker 469*bb4ee6a4SAndroid Build Coastguard Worker // At this point, all of our devices have been created and they have registered their 470*bb4ee6a4SAndroid Build Coastguard Worker // irq events, so we can clone our resample events 471*bb4ee6a4SAndroid Build Coastguard Worker let mut ioapic_resample_events: Vec<Vec<Event>> = 472*bb4ee6a4SAndroid Build Coastguard Worker (0..self.ioapic_pins).map(|_| Vec::new()).collect(); 473*bb4ee6a4SAndroid Build Coastguard Worker let mut pic_resample_events: Vec<Vec<Event>> = 474*bb4ee6a4SAndroid Build Coastguard Worker (0..self.ioapic_pins).map(|_| Vec::new()).collect(); 475*bb4ee6a4SAndroid Build Coastguard Worker 476*bb4ee6a4SAndroid Build Coastguard Worker for evt in self.irq_events.lock().iter().flatten() { 477*bb4ee6a4SAndroid Build Coastguard Worker if (evt.gsi as usize) >= self.ioapic_pins { 478*bb4ee6a4SAndroid Build Coastguard Worker continue; 479*bb4ee6a4SAndroid Build Coastguard Worker } 480*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_evt) = &evt.resample_event { 481*bb4ee6a4SAndroid Build Coastguard Worker ioapic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?); 482*bb4ee6a4SAndroid Build Coastguard Worker pic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?); 483*bb4ee6a4SAndroid Build Coastguard Worker } 484*bb4ee6a4SAndroid Build Coastguard Worker } 485*bb4ee6a4SAndroid Build Coastguard Worker 486*bb4ee6a4SAndroid Build Coastguard Worker // Register resample events with the ioapic 487*bb4ee6a4SAndroid Build Coastguard Worker self.ioapic 488*bb4ee6a4SAndroid Build Coastguard Worker .lock() 489*bb4ee6a4SAndroid Build Coastguard Worker .register_resample_events(ioapic_resample_events); 490*bb4ee6a4SAndroid Build Coastguard Worker // Register resample events with the pic 491*bb4ee6a4SAndroid Build Coastguard Worker self.pic 492*bb4ee6a4SAndroid Build Coastguard Worker .lock() 493*bb4ee6a4SAndroid Build Coastguard Worker .register_resample_events(pic_resample_events); 494*bb4ee6a4SAndroid Build Coastguard Worker 495*bb4ee6a4SAndroid Build Coastguard Worker // Make sure all future irq numbers are >= self.ioapic_pins 496*bb4ee6a4SAndroid Build Coastguard Worker let mut irq_num = resources.allocate_irq().unwrap(); 497*bb4ee6a4SAndroid Build Coastguard Worker while irq_num < self.ioapic_pins as u32 { 498*bb4ee6a4SAndroid Build Coastguard Worker irq_num = resources.allocate_irq().unwrap(); 499*bb4ee6a4SAndroid Build Coastguard Worker } 500*bb4ee6a4SAndroid Build Coastguard Worker 501*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 502*bb4ee6a4SAndroid Build Coastguard Worker } 503*bb4ee6a4SAndroid Build Coastguard Worker process_delayed_irq_events(&mut self) -> Result<()>504*bb4ee6a4SAndroid Build Coastguard Worker fn process_delayed_irq_events(&mut self) -> Result<()> { 505*bb4ee6a4SAndroid Build Coastguard Worker let irq_events = self.irq_events.lock(); 506*bb4ee6a4SAndroid Build Coastguard Worker let mut delayed_events = self.delayed_ioapic_irq_events.lock(); 507*bb4ee6a4SAndroid Build Coastguard Worker delayed_events.events.retain(|&event_index| { 508*bb4ee6a4SAndroid Build Coastguard Worker if let Some(evt) = &irq_events[event_index] { 509*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(mut ioapic) = self.ioapic.try_lock() { 510*bb4ee6a4SAndroid Build Coastguard Worker if evt.resample_event.is_some() { 511*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(evt.gsi as usize, true); 512*bb4ee6a4SAndroid Build Coastguard Worker } else { 513*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(evt.gsi as usize, true); 514*bb4ee6a4SAndroid Build Coastguard Worker ioapic.service_irq(evt.gsi as usize, false); 515*bb4ee6a4SAndroid Build Coastguard Worker } 516*bb4ee6a4SAndroid Build Coastguard Worker 517*bb4ee6a4SAndroid Build Coastguard Worker false 518*bb4ee6a4SAndroid Build Coastguard Worker } else { 519*bb4ee6a4SAndroid Build Coastguard Worker true 520*bb4ee6a4SAndroid Build Coastguard Worker } 521*bb4ee6a4SAndroid Build Coastguard Worker } else { 522*bb4ee6a4SAndroid Build Coastguard Worker true 523*bb4ee6a4SAndroid Build Coastguard Worker } 524*bb4ee6a4SAndroid Build Coastguard Worker }); 525*bb4ee6a4SAndroid Build Coastguard Worker 526*bb4ee6a4SAndroid Build Coastguard Worker if delayed_events.events.is_empty() { 527*bb4ee6a4SAndroid Build Coastguard Worker delayed_events.trigger.wait()?; 528*bb4ee6a4SAndroid Build Coastguard Worker } 529*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 530*bb4ee6a4SAndroid Build Coastguard Worker } 531*bb4ee6a4SAndroid Build Coastguard Worker irq_delayed_event_token(&self) -> Result<Option<Event>>532*bb4ee6a4SAndroid Build Coastguard Worker fn irq_delayed_event_token(&self) -> Result<Option<Event>> { 533*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some( 534*bb4ee6a4SAndroid Build Coastguard Worker self.delayed_ioapic_irq_events.lock().trigger.try_clone()?, 535*bb4ee6a4SAndroid Build Coastguard Worker )) 536*bb4ee6a4SAndroid Build Coastguard Worker } 537*bb4ee6a4SAndroid Build Coastguard Worker check_capability(&self, c: IrqChipCap) -> bool538*bb4ee6a4SAndroid Build Coastguard Worker fn check_capability(&self, c: IrqChipCap) -> bool { 539*bb4ee6a4SAndroid Build Coastguard Worker match c { 540*bb4ee6a4SAndroid Build Coastguard Worker // It appears as though WHPX does not have tsc deadline support because we get guest 541*bb4ee6a4SAndroid Build Coastguard Worker // MSR write failures if we enable it. 542*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::TscDeadlineTimer => false, 543*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/180966070): Figure out how to query x2apic support. 544*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::X2Apic => false, 545*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::MpStateGetSet => false, 546*bb4ee6a4SAndroid Build Coastguard Worker } 547*bb4ee6a4SAndroid Build Coastguard Worker } 548*bb4ee6a4SAndroid Build Coastguard Worker } 549*bb4ee6a4SAndroid Build Coastguard Worker 550*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)] 551*bb4ee6a4SAndroid Build Coastguard Worker struct WhpxSplitIrqChipSnapshot { 552*bb4ee6a4SAndroid Build Coastguard Worker routes: Vec<IrqRoute>, 553*bb4ee6a4SAndroid Build Coastguard Worker } 554*bb4ee6a4SAndroid Build Coastguard Worker 555*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChipX86_64 for WhpxSplitIrqChip { try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>556*bb4ee6a4SAndroid Build Coastguard Worker fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> { 557*bb4ee6a4SAndroid Build Coastguard Worker Ok(Box::new(self.try_clone()?)) 558*bb4ee6a4SAndroid Build Coastguard Worker } 559*bb4ee6a4SAndroid Build Coastguard Worker as_irq_chip(&self) -> &dyn IrqChip560*bb4ee6a4SAndroid Build Coastguard Worker fn as_irq_chip(&self) -> &dyn IrqChip { 561*bb4ee6a4SAndroid Build Coastguard Worker self 562*bb4ee6a4SAndroid Build Coastguard Worker } 563*bb4ee6a4SAndroid Build Coastguard Worker as_irq_chip_mut(&mut self) -> &mut dyn IrqChip564*bb4ee6a4SAndroid Build Coastguard Worker fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip { 565*bb4ee6a4SAndroid Build Coastguard Worker self 566*bb4ee6a4SAndroid Build Coastguard Worker } 567*bb4ee6a4SAndroid Build Coastguard Worker 568*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the PIC get_pic_state(&self, select: PicSelect) -> Result<PicState>569*bb4ee6a4SAndroid Build Coastguard Worker fn get_pic_state(&self, select: PicSelect) -> Result<PicState> { 570*bb4ee6a4SAndroid Build Coastguard Worker Ok(self.pic.lock().get_pic_state(select)) 571*bb4ee6a4SAndroid Build Coastguard Worker } 572*bb4ee6a4SAndroid Build Coastguard Worker 573*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current state of the PIC set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>574*bb4ee6a4SAndroid Build Coastguard Worker fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> { 575*bb4ee6a4SAndroid Build Coastguard Worker self.pic.lock().set_pic_state(select, state); 576*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 577*bb4ee6a4SAndroid Build Coastguard Worker } 578*bb4ee6a4SAndroid Build Coastguard Worker 579*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the IOAPIC get_ioapic_state(&self) -> Result<IoapicState>580*bb4ee6a4SAndroid Build Coastguard Worker fn get_ioapic_state(&self) -> Result<IoapicState> { 581*bb4ee6a4SAndroid Build Coastguard Worker Ok(self.ioapic.lock().get_ioapic_state()) 582*bb4ee6a4SAndroid Build Coastguard Worker } 583*bb4ee6a4SAndroid Build Coastguard Worker 584*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current state of the IOAPIC set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>585*bb4ee6a4SAndroid Build Coastguard Worker fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> { 586*bb4ee6a4SAndroid Build Coastguard Worker self.ioapic.lock().set_ioapic_state(state); 587*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 588*bb4ee6a4SAndroid Build Coastguard Worker } 589*bb4ee6a4SAndroid Build Coastguard Worker 590*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the specified VCPU's local APIC get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>591*bb4ee6a4SAndroid Build Coastguard Worker fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> { 592*bb4ee6a4SAndroid Build Coastguard Worker self.vm.get_vcpu_lapic_state(vcpu_id) 593*bb4ee6a4SAndroid Build Coastguard Worker } 594*bb4ee6a4SAndroid Build Coastguard Worker 595*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current state of the specified VCPU's local APIC set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>596*bb4ee6a4SAndroid Build Coastguard Worker fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> { 597*bb4ee6a4SAndroid Build Coastguard Worker self.vm.set_vcpu_lapic_state(vcpu_id, state) 598*bb4ee6a4SAndroid Build Coastguard Worker } 599*bb4ee6a4SAndroid Build Coastguard Worker lapic_frequency(&self) -> u32600*bb4ee6a4SAndroid Build Coastguard Worker fn lapic_frequency(&self) -> u32 { 601*bb4ee6a4SAndroid Build Coastguard Worker WHPX_LOCAL_APIC_EMULATION_APIC_FREQUENCY 602*bb4ee6a4SAndroid Build Coastguard Worker } 603*bb4ee6a4SAndroid Build Coastguard Worker 604*bb4ee6a4SAndroid Build Coastguard Worker /// Retrieves the state of the PIT. get_pit(&self) -> Result<PitState>605*bb4ee6a4SAndroid Build Coastguard Worker fn get_pit(&self) -> Result<PitState> { 606*bb4ee6a4SAndroid Build Coastguard Worker Ok(self.pit.lock().get_pit_state()) 607*bb4ee6a4SAndroid Build Coastguard Worker } 608*bb4ee6a4SAndroid Build Coastguard Worker 609*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the state of the PIT. set_pit(&mut self, state: &PitState) -> Result<()>610*bb4ee6a4SAndroid Build Coastguard Worker fn set_pit(&mut self, state: &PitState) -> Result<()> { 611*bb4ee6a4SAndroid Build Coastguard Worker self.pit.lock().set_pit_state(state); 612*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 613*bb4ee6a4SAndroid Build Coastguard Worker } 614*bb4ee6a4SAndroid Build Coastguard Worker 615*bb4ee6a4SAndroid Build Coastguard Worker /// Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused. 616*bb4ee6a4SAndroid Build Coastguard Worker /// devices::Pit uses 0x61. pit_uses_speaker_port(&self) -> bool617*bb4ee6a4SAndroid Build Coastguard Worker fn pit_uses_speaker_port(&self) -> bool { 618*bb4ee6a4SAndroid Build Coastguard Worker true 619*bb4ee6a4SAndroid Build Coastguard Worker } 620*bb4ee6a4SAndroid Build Coastguard Worker snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value>621*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value> { 622*bb4ee6a4SAndroid Build Coastguard Worker serde_json::to_value(&WhpxSplitIrqChipSnapshot { 623*bb4ee6a4SAndroid Build Coastguard Worker routes: self.routes.lock().get_routes(), 624*bb4ee6a4SAndroid Build Coastguard Worker }) 625*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to snapshot WhpxSplitIrqChip") 626*bb4ee6a4SAndroid Build Coastguard Worker } 627*bb4ee6a4SAndroid Build Coastguard Worker restore_chip_specific(&mut self, data: serde_json::Value) -> anyhow::Result<()>628*bb4ee6a4SAndroid Build Coastguard Worker fn restore_chip_specific(&mut self, data: serde_json::Value) -> anyhow::Result<()> { 629*bb4ee6a4SAndroid Build Coastguard Worker let mut deser: WhpxSplitIrqChipSnapshot = 630*bb4ee6a4SAndroid Build Coastguard Worker serde_json::from_value(data).context("failed to deserialize WhpxSplitIrqChip")?; 631*bb4ee6a4SAndroid Build Coastguard Worker self.set_irq_routes(deser.routes.as_slice())?; 632*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 633*bb4ee6a4SAndroid Build Coastguard Worker } 634*bb4ee6a4SAndroid Build Coastguard Worker } 635