xref: /aosp_15_r20/external/crosvm/devices/src/irqchip/x86_64.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::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