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::ops::Index; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::vec::Vec; 7*bb4ee6a4SAndroid Build Coastguard Worker 8*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow; 9*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context; 10*bb4ee6a4SAndroid Build Coastguard Worker use base::Error; 11*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 12*bb4ee6a4SAndroid Build Coastguard Worker use base::Result; 13*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IoapicState; 14*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute; 15*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSource; 16*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqSourceChip; 17*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::LapicState; 18*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MPState; 19*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicSelect; 20*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PicState; 21*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PitState; 22*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize; 23*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize; 24*bb4ee6a4SAndroid Build Coastguard Worker 25*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip; 26*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipCap; 27*bb4ee6a4SAndroid Build Coastguard Worker 28*bb4ee6a4SAndroid Build Coastguard Worker pub trait IrqChipX86_64: IrqChip { 29*bb4ee6a4SAndroid Build Coastguard Worker // Clones this trait as a `Box` version of itself. try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>30*bb4ee6a4SAndroid Build Coastguard Worker fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>; 31*bb4ee6a4SAndroid Build Coastguard Worker 32*bb4ee6a4SAndroid Build Coastguard Worker // Get this as the super-trait IrqChip. as_irq_chip(&self) -> &dyn IrqChip33*bb4ee6a4SAndroid Build Coastguard Worker fn as_irq_chip(&self) -> &dyn IrqChip; 34*bb4ee6a4SAndroid Build Coastguard Worker 35*bb4ee6a4SAndroid Build Coastguard Worker // Get this as the mutable super-trait IrqChip. as_irq_chip_mut(&mut self) -> &mut dyn IrqChip36*bb4ee6a4SAndroid Build Coastguard Worker fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip; 37*bb4ee6a4SAndroid Build Coastguard Worker 38*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the PIC get_pic_state(&self, select: PicSelect) -> Result<PicState>39*bb4ee6a4SAndroid Build Coastguard Worker fn get_pic_state(&self, select: PicSelect) -> Result<PicState>; 40*bb4ee6a4SAndroid Build Coastguard Worker 41*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current state of the PIC set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>42*bb4ee6a4SAndroid Build Coastguard Worker fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>; 43*bb4ee6a4SAndroid Build Coastguard Worker 44*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the IOAPIC get_ioapic_state(&self) -> Result<IoapicState>45*bb4ee6a4SAndroid Build Coastguard Worker fn get_ioapic_state(&self) -> Result<IoapicState>; 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current state of the IOAPIC set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>48*bb4ee6a4SAndroid Build Coastguard Worker fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>; 49*bb4ee6a4SAndroid Build Coastguard Worker 50*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current state of the specified VCPU's local APIC get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>51*bb4ee6a4SAndroid Build Coastguard Worker fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>; 52*bb4ee6a4SAndroid Build Coastguard Worker 53*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<()>54*bb4ee6a4SAndroid Build Coastguard Worker fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>; 55*bb4ee6a4SAndroid Build Coastguard Worker 56*bb4ee6a4SAndroid Build Coastguard Worker /// Get the lapic frequency in Hz lapic_frequency(&self) -> u3257*bb4ee6a4SAndroid Build Coastguard Worker fn lapic_frequency(&self) -> u32; 58*bb4ee6a4SAndroid Build Coastguard Worker 59*bb4ee6a4SAndroid Build Coastguard Worker /// Retrieves the state of the PIT. get_pit(&self) -> Result<PitState>60*bb4ee6a4SAndroid Build Coastguard Worker fn get_pit(&self) -> Result<PitState>; 61*bb4ee6a4SAndroid Build Coastguard Worker 62*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the state of the PIT. set_pit(&mut self, state: &PitState) -> Result<()>63*bb4ee6a4SAndroid Build Coastguard Worker fn set_pit(&mut self, state: &PitState) -> Result<()>; 64*bb4ee6a4SAndroid Build Coastguard Worker 65*bb4ee6a4SAndroid Build Coastguard Worker /// Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused. pit_uses_speaker_port(&self) -> bool66*bb4ee6a4SAndroid Build Coastguard Worker fn pit_uses_speaker_port(&self) -> bool; 67*bb4ee6a4SAndroid Build Coastguard Worker 68*bb4ee6a4SAndroid Build Coastguard Worker /// Snapshot state specific to different IrqChips. snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value>69*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot_chip_specific(&self) -> anyhow::Result<serde_json::Value>; 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker /// Restore state specific to different IrqChips. restore_chip_specific(&mut self, data: serde_json::Value) -> anyhow::Result<()>72*bb4ee6a4SAndroid Build Coastguard Worker fn restore_chip_specific(&mut self, data: serde_json::Value) -> anyhow::Result<()>; 73*bb4ee6a4SAndroid Build Coastguard Worker 74*bb4ee6a4SAndroid Build Coastguard Worker /// Snapshot state common to IrqChips. snapshot(&self, cpus_num: usize) -> anyhow::Result<serde_json::Value>75*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&self, cpus_num: usize) -> anyhow::Result<serde_json::Value> { 76*bb4ee6a4SAndroid Build Coastguard Worker let mut lapics: Vec<LapicState> = Vec::new(); 77*bb4ee6a4SAndroid Build Coastguard Worker let mut mp_states: Vec<MPState> = Vec::new(); 78*bb4ee6a4SAndroid Build Coastguard Worker let has_mp_states = self.check_capability(IrqChipCap::MpStateGetSet); 79*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..cpus_num { 80*bb4ee6a4SAndroid Build Coastguard Worker lapics.push(self.get_lapic_state(i)?); 81*bb4ee6a4SAndroid Build Coastguard Worker if has_mp_states { 82*bb4ee6a4SAndroid Build Coastguard Worker mp_states.push(self.get_mp_state(i)?); 83*bb4ee6a4SAndroid Build Coastguard Worker } 84*bb4ee6a4SAndroid Build Coastguard Worker } 85*bb4ee6a4SAndroid Build Coastguard Worker serde_json::to_value(IrqChipSnapshot { 86*bb4ee6a4SAndroid Build Coastguard Worker ioapic_state: self.get_ioapic_state()?, 87*bb4ee6a4SAndroid Build Coastguard Worker lapic_state: lapics, 88*bb4ee6a4SAndroid Build Coastguard Worker pic_state_1: self.get_pic_state(PicSelect::Primary)?, 89*bb4ee6a4SAndroid Build Coastguard Worker pic_state_2: self.get_pic_state(PicSelect::Secondary)?, 90*bb4ee6a4SAndroid Build Coastguard Worker pit_state: self.get_pit()?, 91*bb4ee6a4SAndroid Build Coastguard Worker chip_specific_state: self.snapshot_chip_specific()?, 92*bb4ee6a4SAndroid Build Coastguard Worker mp_state: mp_states, 93*bb4ee6a4SAndroid Build Coastguard Worker }) 94*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to serialize KvmKernelIrqChip") 95*bb4ee6a4SAndroid Build Coastguard Worker } 96*bb4ee6a4SAndroid Build Coastguard Worker 97*bb4ee6a4SAndroid Build Coastguard Worker /// Restore state common to IrqChips. restore(&mut self, data: serde_json::Value, vcpus_num: usize) -> anyhow::Result<()>98*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value, vcpus_num: usize) -> anyhow::Result<()> { 99*bb4ee6a4SAndroid Build Coastguard Worker let deser: IrqChipSnapshot = 100*bb4ee6a4SAndroid Build Coastguard Worker serde_json::from_value(data).context("failed to deserialize data")?; 101*bb4ee6a4SAndroid Build Coastguard Worker 102*bb4ee6a4SAndroid Build Coastguard Worker if deser.lapic_state.len() != vcpus_num { 103*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!( 104*bb4ee6a4SAndroid Build Coastguard Worker "IrqChip has the wrong number of LAPIC state snapshots: got {}, expected {}", 105*bb4ee6a4SAndroid Build Coastguard Worker deser.lapic_state.len(), 106*bb4ee6a4SAndroid Build Coastguard Worker vcpus_num 107*bb4ee6a4SAndroid Build Coastguard Worker )); 108*bb4ee6a4SAndroid Build Coastguard Worker } 109*bb4ee6a4SAndroid Build Coastguard Worker let supports_mp_states = self.check_capability(IrqChipCap::MpStateGetSet); 110*bb4ee6a4SAndroid Build Coastguard Worker 111*bb4ee6a4SAndroid Build Coastguard Worker if supports_mp_states { 112*bb4ee6a4SAndroid Build Coastguard Worker if deser.mp_state.len() != vcpus_num { 113*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!( 114*bb4ee6a4SAndroid Build Coastguard Worker "IrqChip has the wrong number of mp state snapshots: got {}, expected {}", 115*bb4ee6a4SAndroid Build Coastguard Worker deser.mp_state.len(), 116*bb4ee6a4SAndroid Build Coastguard Worker vcpus_num 117*bb4ee6a4SAndroid Build Coastguard Worker )); 118*bb4ee6a4SAndroid Build Coastguard Worker } 119*bb4ee6a4SAndroid Build Coastguard Worker } else if !deser.mp_state.is_empty() { 120*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!( 121*bb4ee6a4SAndroid Build Coastguard Worker "IrqChip does not support mp state, but mp state was in the snapshot" 122*bb4ee6a4SAndroid Build Coastguard Worker )); 123*bb4ee6a4SAndroid Build Coastguard Worker } 124*bb4ee6a4SAndroid Build Coastguard Worker 125*bb4ee6a4SAndroid Build Coastguard Worker self.set_pit(&deser.pit_state)?; 126*bb4ee6a4SAndroid Build Coastguard Worker self.set_pic_state(PicSelect::Primary, &deser.pic_state_1) 127*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set primary PIC")?; 128*bb4ee6a4SAndroid Build Coastguard Worker self.set_pic_state(PicSelect::Secondary, &deser.pic_state_2) 129*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set secondary PIC")?; 130*bb4ee6a4SAndroid Build Coastguard Worker self.set_ioapic_state(&deser.ioapic_state) 131*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set IOAPIC state")?; 132*bb4ee6a4SAndroid Build Coastguard Worker self.restore_chip_specific(deser.chip_specific_state) 133*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set chip specific data")?; 134*bb4ee6a4SAndroid Build Coastguard Worker for (i, lapic) in deser.lapic_state.iter().enumerate() { 135*bb4ee6a4SAndroid Build Coastguard Worker self.set_lapic_state(i, lapic) 136*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set LAPIC state")?; 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker 139*bb4ee6a4SAndroid Build Coastguard Worker if supports_mp_states { 140*bb4ee6a4SAndroid Build Coastguard Worker for (i, mp_state) in deser.mp_state.iter().enumerate() { 141*bb4ee6a4SAndroid Build Coastguard Worker self.set_mp_state(i, mp_state) 142*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to set mp state")?; 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker } 145*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 146*bb4ee6a4SAndroid Build Coastguard Worker } 147*bb4ee6a4SAndroid Build Coastguard Worker } 148*bb4ee6a4SAndroid Build Coastguard Worker 149*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)] 150*bb4ee6a4SAndroid Build Coastguard Worker struct IrqChipSnapshot { 151*bb4ee6a4SAndroid Build Coastguard Worker ioapic_state: IoapicState, 152*bb4ee6a4SAndroid Build Coastguard Worker lapic_state: Vec<LapicState>, 153*bb4ee6a4SAndroid Build Coastguard Worker pic_state_1: PicState, 154*bb4ee6a4SAndroid Build Coastguard Worker pic_state_2: PicState, 155*bb4ee6a4SAndroid Build Coastguard Worker pit_state: PitState, 156*bb4ee6a4SAndroid Build Coastguard Worker chip_specific_state: serde_json::Value, 157*bb4ee6a4SAndroid Build Coastguard Worker mp_state: Vec<MPState>, 158*bb4ee6a4SAndroid Build Coastguard Worker } 159*bb4ee6a4SAndroid Build Coastguard Worker 160*bb4ee6a4SAndroid Build Coastguard Worker /// A container for x86 IrqRoutes, grouped by GSI. 161*bb4ee6a4SAndroid Build Coastguard Worker pub struct Routes { 162*bb4ee6a4SAndroid Build Coastguard Worker /// A list of routes, indexed by GSI. Each GSI can map to zero or more routes, so this is a 163*bb4ee6a4SAndroid Build Coastguard Worker /// Vec of Vecs. Specifically, a GSI can map to: 164*bb4ee6a4SAndroid Build Coastguard Worker /// * no routes; or 165*bb4ee6a4SAndroid Build Coastguard Worker /// * one IrqSource::Msi route; or 166*bb4ee6a4SAndroid Build Coastguard Worker /// * one or more IrqSource::Irqchip routes (PicPrimary, PicSecondary, or Ioapic) 167*bb4ee6a4SAndroid Build Coastguard Worker routes: Vec<Vec<IrqSource>>, 168*bb4ee6a4SAndroid Build Coastguard Worker } 169*bb4ee6a4SAndroid Build Coastguard Worker 170*bb4ee6a4SAndroid Build Coastguard Worker impl Routes { 171*bb4ee6a4SAndroid Build Coastguard Worker /// Constructs a new `Routes` with an empty routing table. new() -> Self172*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> Self { 173*bb4ee6a4SAndroid Build Coastguard Worker Routes { routes: vec![] } 174*bb4ee6a4SAndroid Build Coastguard Worker } 175*bb4ee6a4SAndroid Build Coastguard Worker 176*bb4ee6a4SAndroid Build Coastguard Worker /// Inserts a route, replacing any existing route that conflicts. Two routes conflict if they 177*bb4ee6a4SAndroid Build Coastguard Worker /// have the same GSI, and they're both `IrqSource::Irqchip` routes with the same chip or 178*bb4ee6a4SAndroid Build Coastguard Worker /// they're both `IrqSource::Msi`. Returns Err if an `IrqSource::Irqchip` and `IrqSource::Msi` 179*bb4ee6a4SAndroid Build Coastguard Worker /// route have the same GSI. add(&mut self, route: IrqRoute) -> Result<()>180*bb4ee6a4SAndroid Build Coastguard Worker pub fn add(&mut self, route: IrqRoute) -> Result<()> { 181*bb4ee6a4SAndroid Build Coastguard Worker let routes = self.get_mut(route.gsi as usize); 182*bb4ee6a4SAndroid Build Coastguard Worker if routes.iter().any(|r| !Self::same_source(&route.source, r)) { 183*bb4ee6a4SAndroid Build Coastguard Worker // We keep an invariant that legacy and MSI routes can't be mixed on the same GSI. 184*bb4ee6a4SAndroid Build Coastguard Worker // Irqchip routes are only on GSIs [0..24) and Msi routes are only on GSIs >= 24. This 185*bb4ee6a4SAndroid Build Coastguard Worker // guarantees that in UserspaceIrqChip, the ioapic's incoming Irqchip routes and 186*bb4ee6a4SAndroid Build Coastguard Worker // outgoing Msi routes can't trigger each other in a cycle. 187*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EINVAL)); 188*bb4ee6a4SAndroid Build Coastguard Worker } 189*bb4ee6a4SAndroid Build Coastguard Worker routes.retain(|r| !Self::conflict(&route.source, r)); 190*bb4ee6a4SAndroid Build Coastguard Worker routes.push(route.source); 191*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 192*bb4ee6a4SAndroid Build Coastguard Worker } 193*bb4ee6a4SAndroid Build Coastguard Worker 194*bb4ee6a4SAndroid Build Coastguard Worker /// Deletes all existing routes and replaces them with `routes`. If two routes in `routes` 195*bb4ee6a4SAndroid Build Coastguard Worker /// conflict with each other, the one earlier in the slice is dropped. replace_all(&mut self, routes: &[IrqRoute]) -> Result<()>196*bb4ee6a4SAndroid Build Coastguard Worker pub fn replace_all(&mut self, routes: &[IrqRoute]) -> Result<()> { 197*bb4ee6a4SAndroid Build Coastguard Worker self.routes.clear(); 198*bb4ee6a4SAndroid Build Coastguard Worker for r in routes { 199*bb4ee6a4SAndroid Build Coastguard Worker self.add(*r)?; 200*bb4ee6a4SAndroid Build Coastguard Worker } 201*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker 204*bb4ee6a4SAndroid Build Coastguard Worker /// Default x86 routing table. Pins 0-7 go to primary pic and ioapic, pins 8-15 go to secondary 205*bb4ee6a4SAndroid Build Coastguard Worker /// pic and ioapic, and pins 16-23 go only to the ioapic. default_pic_ioapic_routes(ioapic_pins: usize) -> Vec<IrqRoute>206*bb4ee6a4SAndroid Build Coastguard Worker pub fn default_pic_ioapic_routes(ioapic_pins: usize) -> Vec<IrqRoute> { 207*bb4ee6a4SAndroid Build Coastguard Worker let mut routes: Vec<IrqRoute> = Vec::new(); 208*bb4ee6a4SAndroid Build Coastguard Worker 209*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..8 { 210*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicPrimary, i)); 211*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute::ioapic_irq_route(i)); 212*bb4ee6a4SAndroid Build Coastguard Worker } 213*bb4ee6a4SAndroid Build Coastguard Worker for i in 8..16 { 214*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicSecondary, i)); 215*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute::ioapic_irq_route(i)); 216*bb4ee6a4SAndroid Build Coastguard Worker } 217*bb4ee6a4SAndroid Build Coastguard Worker for i in 16..ioapic_pins as u32 { 218*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute::ioapic_irq_route(i)); 219*bb4ee6a4SAndroid Build Coastguard Worker } 220*bb4ee6a4SAndroid Build Coastguard Worker 221*bb4ee6a4SAndroid Build Coastguard Worker routes 222*bb4ee6a4SAndroid Build Coastguard Worker } 223*bb4ee6a4SAndroid Build Coastguard Worker 224*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the routes as a flat Vec of `IrqRoute`s. get_routes(&self) -> Vec<IrqRoute>225*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_routes(&self) -> Vec<IrqRoute> { 226*bb4ee6a4SAndroid Build Coastguard Worker let mut routes = Vec::with_capacity(self.routes.len()); 227*bb4ee6a4SAndroid Build Coastguard Worker for (gsi, sources) in self.routes.iter().enumerate() { 228*bb4ee6a4SAndroid Build Coastguard Worker for source in sources.iter() { 229*bb4ee6a4SAndroid Build Coastguard Worker routes.push(IrqRoute { 230*bb4ee6a4SAndroid Build Coastguard Worker gsi: gsi.try_into().expect("GSIs must be < u32::MAX"), 231*bb4ee6a4SAndroid Build Coastguard Worker source: *source, 232*bb4ee6a4SAndroid Build Coastguard Worker }); 233*bb4ee6a4SAndroid Build Coastguard Worker } 234*bb4ee6a4SAndroid Build Coastguard Worker } 235*bb4ee6a4SAndroid Build Coastguard Worker routes 236*bb4ee6a4SAndroid Build Coastguard Worker } 237*bb4ee6a4SAndroid Build Coastguard Worker 238*bb4ee6a4SAndroid Build Coastguard Worker /// Determines whether or not two irq routes on the same GSI conflict. 239*bb4ee6a4SAndroid Build Coastguard Worker /// Returns true if they conflict. conflict(source: &IrqSource, other: &IrqSource) -> bool240*bb4ee6a4SAndroid Build Coastguard Worker fn conflict(source: &IrqSource, other: &IrqSource) -> bool { 241*bb4ee6a4SAndroid Build Coastguard Worker use IrqSource::*; 242*bb4ee6a4SAndroid Build Coastguard Worker 243*bb4ee6a4SAndroid Build Coastguard Worker // If they're both MSI then they conflict. 244*bb4ee6a4SAndroid Build Coastguard Worker if let (Msi { .. }, Msi { .. }) = (source, other) { 245*bb4ee6a4SAndroid Build Coastguard Worker return true; 246*bb4ee6a4SAndroid Build Coastguard Worker } 247*bb4ee6a4SAndroid Build Coastguard Worker 248*bb4ee6a4SAndroid Build Coastguard Worker // If the route chips match then they conflict. 249*bb4ee6a4SAndroid Build Coastguard Worker if let ( 250*bb4ee6a4SAndroid Build Coastguard Worker Irqchip { chip, .. }, 251*bb4ee6a4SAndroid Build Coastguard Worker Irqchip { 252*bb4ee6a4SAndroid Build Coastguard Worker chip: other_chip, .. 253*bb4ee6a4SAndroid Build Coastguard Worker }, 254*bb4ee6a4SAndroid Build Coastguard Worker ) = (source, other) 255*bb4ee6a4SAndroid Build Coastguard Worker { 256*bb4ee6a4SAndroid Build Coastguard Worker return chip == other_chip; 257*bb4ee6a4SAndroid Build Coastguard Worker } 258*bb4ee6a4SAndroid Build Coastguard Worker 259*bb4ee6a4SAndroid Build Coastguard Worker // Otherwise they do not conflict. 260*bb4ee6a4SAndroid Build Coastguard Worker false 261*bb4ee6a4SAndroid Build Coastguard Worker } 262*bb4ee6a4SAndroid Build Coastguard Worker 263*bb4ee6a4SAndroid Build Coastguard Worker /// Determines whether two routes have the same IrqSource variant (IrqSource::Irqchip or 264*bb4ee6a4SAndroid Build Coastguard Worker /// IrqSource::Msi). same_source(source: &IrqSource, other: &IrqSource) -> bool265*bb4ee6a4SAndroid Build Coastguard Worker fn same_source(source: &IrqSource, other: &IrqSource) -> bool { 266*bb4ee6a4SAndroid Build Coastguard Worker use IrqSource::*; 267*bb4ee6a4SAndroid Build Coastguard Worker matches!( 268*bb4ee6a4SAndroid Build Coastguard Worker (source, other), 269*bb4ee6a4SAndroid Build Coastguard Worker (Irqchip { .. }, Irqchip { .. }) | (Msi { .. }, Msi { .. }) 270*bb4ee6a4SAndroid Build Coastguard Worker ) 271*bb4ee6a4SAndroid Build Coastguard Worker } 272*bb4ee6a4SAndroid Build Coastguard Worker 273*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the routes vec for `irq`. If `irq` is past the end of self.routes, then self.routes 274*bb4ee6a4SAndroid Build Coastguard Worker /// is first resized with empty vecs. get_mut(&mut self, irq: usize) -> &mut Vec<IrqSource>275*bb4ee6a4SAndroid Build Coastguard Worker fn get_mut(&mut self, irq: usize) -> &mut Vec<IrqSource> { 276*bb4ee6a4SAndroid Build Coastguard Worker if irq >= self.routes.len() { 277*bb4ee6a4SAndroid Build Coastguard Worker self.routes.resize_with(irq + 1, Vec::new); 278*bb4ee6a4SAndroid Build Coastguard Worker } 279*bb4ee6a4SAndroid Build Coastguard Worker self.routes.get_mut(irq).unwrap() 280*bb4ee6a4SAndroid Build Coastguard Worker } 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker 283*bb4ee6a4SAndroid Build Coastguard Worker impl Default for Routes { default() -> Self284*bb4ee6a4SAndroid Build Coastguard Worker fn default() -> Self { 285*bb4ee6a4SAndroid Build Coastguard Worker Self::new() 286*bb4ee6a4SAndroid Build Coastguard Worker } 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker 289*bb4ee6a4SAndroid Build Coastguard Worker const EMPTY_ROUTE: [IrqSource; 0] = []; 290*bb4ee6a4SAndroid Build Coastguard Worker 291*bb4ee6a4SAndroid Build Coastguard Worker impl Index<usize> for Routes { 292*bb4ee6a4SAndroid Build Coastguard Worker type Output = [IrqSource]; 293*bb4ee6a4SAndroid Build Coastguard Worker 294*bb4ee6a4SAndroid Build Coastguard Worker /// Returns all routes for `irq`, or an empty slice if no routes registered for `irq`. index(&self, irq: usize) -> &Self::Output295*bb4ee6a4SAndroid Build Coastguard Worker fn index(&self, irq: usize) -> &Self::Output { 296*bb4ee6a4SAndroid Build Coastguard Worker if irq < self.routes.len() { 297*bb4ee6a4SAndroid Build Coastguard Worker self.routes[irq].as_slice() 298*bb4ee6a4SAndroid Build Coastguard Worker } else { 299*bb4ee6a4SAndroid Build Coastguard Worker &EMPTY_ROUTE 300*bb4ee6a4SAndroid Build Coastguard Worker } 301*bb4ee6a4SAndroid Build Coastguard Worker } 302*bb4ee6a4SAndroid Build Coastguard Worker } 303*bb4ee6a4SAndroid Build Coastguard Worker 304*bb4ee6a4SAndroid Build Coastguard Worker pub(super) struct DelayedIoApicIrqEvents { 305*bb4ee6a4SAndroid Build Coastguard Worker /// Vec of ioapic irq events that have been delayed because the ioapic was locked when 306*bb4ee6a4SAndroid Build Coastguard Worker /// service_irq was called on the irqchip. 307*bb4ee6a4SAndroid Build Coastguard Worker pub events: Vec<usize>, 308*bb4ee6a4SAndroid Build Coastguard Worker /// Event which is meant to trigger process of any irqs events that were delayed. 309*bb4ee6a4SAndroid Build Coastguard Worker pub trigger: Event, 310*bb4ee6a4SAndroid Build Coastguard Worker } 311*bb4ee6a4SAndroid Build Coastguard Worker 312*bb4ee6a4SAndroid Build Coastguard Worker impl DelayedIoApicIrqEvents { new() -> Result<Self>313*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> Result<Self> { 314*bb4ee6a4SAndroid Build Coastguard Worker Ok(DelayedIoApicIrqEvents { 315*bb4ee6a4SAndroid Build Coastguard Worker events: Vec::new(), 316*bb4ee6a4SAndroid Build Coastguard Worker trigger: Event::new()?, 317*bb4ee6a4SAndroid Build Coastguard Worker }) 318*bb4ee6a4SAndroid Build Coastguard Worker } 319*bb4ee6a4SAndroid Build Coastguard Worker } 320