devices/irqchip/
x86_64.rs1use std::ops::Index;
6use std::vec::Vec;
7
8use anyhow::anyhow;
9use anyhow::Context;
10use base::Error;
11use base::Event;
12use base::Result;
13use hypervisor::IoapicState;
14use hypervisor::IrqRoute;
15use hypervisor::IrqSource;
16use hypervisor::IrqSourceChip;
17use hypervisor::LapicState;
18use hypervisor::MPState;
19use hypervisor::PicSelect;
20use hypervisor::PicState;
21use hypervisor::PitState;
22use serde::Deserialize;
23use serde::Serialize;
24use snapshot::AnySnapshot;
25
26use crate::IrqChip;
27use crate::IrqChipCap;
28
29pub trait IrqChipX86_64: IrqChip {
30 fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>;
32
33 fn as_irq_chip(&self) -> &dyn IrqChip;
35
36 fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip;
38
39 fn get_pic_state(&self, select: PicSelect) -> Result<PicState>;
41
42 fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>;
44
45 fn get_ioapic_state(&self) -> Result<IoapicState>;
47
48 fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>;
50
51 fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>;
53
54 fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>;
56
57 fn lapic_frequency(&self) -> u32;
59
60 fn get_pit(&self) -> Result<PitState>;
62
63 fn set_pit(&mut self, state: &PitState) -> Result<()>;
65
66 fn pit_uses_speaker_port(&self) -> bool;
68
69 fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot>;
71
72 fn restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()>;
74
75 fn snapshot(&self, cpus_num: usize) -> anyhow::Result<AnySnapshot> {
77 let mut lapics: Vec<LapicState> = Vec::new();
78 let mut mp_states: Vec<MPState> = Vec::new();
79 let has_mp_states = self.check_capability(IrqChipCap::MpStateGetSet);
80 for i in 0..cpus_num {
81 lapics.push(self.get_lapic_state(i)?);
82 if has_mp_states {
83 mp_states.push(self.get_mp_state(i)?);
84 }
85 }
86 AnySnapshot::to_any(IrqChipSnapshot {
87 ioapic_state: self.get_ioapic_state()?,
88 lapic_state: lapics,
89 pic_state_1: self.get_pic_state(PicSelect::Primary)?,
90 pic_state_2: self.get_pic_state(PicSelect::Secondary)?,
91 pit_state: self.get_pit()?,
92 chip_specific_state: self.snapshot_chip_specific()?,
93 mp_state: mp_states,
94 })
95 .context("failed to serialize KvmKernelIrqChip")
96 }
97
98 fn restore(&mut self, data: AnySnapshot, vcpus_num: usize) -> anyhow::Result<()> {
100 let deser: IrqChipSnapshot =
101 AnySnapshot::from_any(data).context("failed to deserialize data")?;
102
103 if deser.lapic_state.len() != vcpus_num {
104 return Err(anyhow!(
105 "IrqChip has the wrong number of LAPIC state snapshots: got {}, expected {}",
106 deser.lapic_state.len(),
107 vcpus_num
108 ));
109 }
110 let supports_mp_states = self.check_capability(IrqChipCap::MpStateGetSet);
111
112 if supports_mp_states {
113 if deser.mp_state.len() != vcpus_num {
114 return Err(anyhow!(
115 "IrqChip has the wrong number of mp state snapshots: got {}, expected {}",
116 deser.mp_state.len(),
117 vcpus_num
118 ));
119 }
120 } else if !deser.mp_state.is_empty() {
121 return Err(anyhow!(
122 "IrqChip does not support mp state, but mp state was in the snapshot"
123 ));
124 }
125
126 self.set_pit(&deser.pit_state)?;
127 self.set_pic_state(PicSelect::Primary, &deser.pic_state_1)
128 .context("failed to set primary PIC")?;
129 self.set_pic_state(PicSelect::Secondary, &deser.pic_state_2)
130 .context("failed to set secondary PIC")?;
131 self.set_ioapic_state(&deser.ioapic_state)
132 .context("failed to set IOAPIC state")?;
133 self.restore_chip_specific(deser.chip_specific_state)
134 .context("failed to set chip specific data")?;
135 for (i, lapic) in deser.lapic_state.iter().enumerate() {
136 self.set_lapic_state(i, lapic)
137 .context("failed to set LAPIC state")?;
138 }
139
140 if supports_mp_states {
141 for (i, mp_state) in deser.mp_state.iter().enumerate() {
142 self.set_mp_state(i, mp_state)
143 .context("failed to set mp state")?;
144 }
145 }
146 Ok(())
147 }
148}
149
150#[derive(Serialize, Deserialize)]
151struct IrqChipSnapshot {
152 ioapic_state: IoapicState,
153 lapic_state: Vec<LapicState>,
154 pic_state_1: PicState,
155 pic_state_2: PicState,
156 pit_state: PitState,
157 chip_specific_state: AnySnapshot,
158 mp_state: Vec<MPState>,
159}
160
161pub struct Routes {
163 routes: Vec<Vec<IrqSource>>,
169}
170
171impl Routes {
172 pub fn new() -> Self {
174 Routes { routes: vec![] }
175 }
176
177 pub fn add(&mut self, route: IrqRoute) -> Result<()> {
182 let routes = self.get_mut(route.gsi as usize);
183 if routes.iter().any(|r| !Self::same_source(&route.source, r)) {
184 return Err(Error::new(libc::EINVAL));
189 }
190 routes.retain(|r| !Self::conflict(&route.source, r));
191 routes.push(route.source);
192 Ok(())
193 }
194
195 pub fn replace_all(&mut self, routes: &[IrqRoute]) -> Result<()> {
198 self.routes.clear();
199 for r in routes {
200 self.add(*r)?;
201 }
202 Ok(())
203 }
204
205 pub fn default_pic_ioapic_routes(ioapic_pins: usize) -> Vec<IrqRoute> {
208 let mut routes: Vec<IrqRoute> = Vec::new();
209
210 for i in 0..8 {
211 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicPrimary, i));
212 routes.push(IrqRoute::ioapic_irq_route(i));
213 }
214 for i in 8..16 {
215 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicSecondary, i));
216 routes.push(IrqRoute::ioapic_irq_route(i));
217 }
218 for i in 16..ioapic_pins as u32 {
219 routes.push(IrqRoute::ioapic_irq_route(i));
220 }
221
222 routes
223 }
224
225 pub fn get_routes(&self) -> Vec<IrqRoute> {
227 let mut routes = Vec::with_capacity(self.routes.len());
228 for (gsi, sources) in self.routes.iter().enumerate() {
229 for source in sources.iter() {
230 routes.push(IrqRoute {
231 gsi: gsi.try_into().expect("GSIs must be < u32::MAX"),
232 source: *source,
233 });
234 }
235 }
236 routes
237 }
238
239 fn conflict(source: &IrqSource, other: &IrqSource) -> bool {
242 use IrqSource::*;
243
244 if let (Msi { .. }, Msi { .. }) = (source, other) {
246 return true;
247 }
248
249 if let (
251 Irqchip { chip, .. },
252 Irqchip {
253 chip: other_chip, ..
254 },
255 ) = (source, other)
256 {
257 return chip == other_chip;
258 }
259
260 false
262 }
263
264 fn same_source(source: &IrqSource, other: &IrqSource) -> bool {
267 use IrqSource::*;
268 matches!(
269 (source, other),
270 (Irqchip { .. }, Irqchip { .. }) | (Msi { .. }, Msi { .. })
271 )
272 }
273
274 fn get_mut(&mut self, irq: usize) -> &mut Vec<IrqSource> {
277 if irq >= self.routes.len() {
278 self.routes.resize_with(irq + 1, Vec::new);
279 }
280 self.routes.get_mut(irq).unwrap()
281 }
282}
283
284impl Default for Routes {
285 fn default() -> Self {
286 Self::new()
287 }
288}
289
290const EMPTY_ROUTE: [IrqSource; 0] = [];
291
292impl Index<usize> for Routes {
293 type Output = [IrqSource];
294
295 fn index(&self, irq: usize) -> &Self::Output {
297 if irq < self.routes.len() {
298 self.routes[irq].as_slice()
299 } else {
300 &EMPTY_ROUTE
301 }
302 }
303}
304
305pub(super) struct DelayedIoApicIrqEvents {
306 pub events: Vec<usize>,
309 pub trigger: Event,
311}
312
313impl DelayedIoApicIrqEvents {
314 pub fn new() -> Result<Self> {
315 Ok(DelayedIoApicIrqEvents {
316 events: Vec::new(),
317 trigger: Event::new()?,
318 })
319 }
320}