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 get_pic_state(&self, select: PicSelect) -> Result<PicState>;
32
33 fn set_pic_state(&self, select: PicSelect, state: &PicState) -> Result<()>;
35
36 fn get_ioapic_state(&self) -> Result<IoapicState>;
38
39 fn set_ioapic_state(&self, state: &IoapicState) -> Result<()>;
41
42 fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>;
44
45 fn set_lapic_state(&self, vcpu_id: usize, state: &LapicState) -> Result<()>;
47
48 fn lapic_frequency(&self) -> u32;
50
51 fn get_pit(&self) -> Result<PitState>;
53
54 fn set_pit(&self, state: &PitState) -> Result<()>;
56
57 fn pit_uses_speaker_port(&self) -> bool;
59
60 fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot>;
62
63 fn restore_chip_specific(&self, data: AnySnapshot) -> anyhow::Result<()>;
65
66 fn snapshot(&self, cpus_num: usize) -> anyhow::Result<AnySnapshot> {
68 let mut lapics: Vec<LapicState> = Vec::new();
69 let mut mp_states: Vec<MPState> = Vec::new();
70 let has_mp_states = self.check_capability(IrqChipCap::MpStateGetSet);
71 for i in 0..cpus_num {
72 lapics.push(self.get_lapic_state(i)?);
73 if has_mp_states {
74 mp_states.push(self.get_mp_state(i)?);
75 }
76 }
77 AnySnapshot::to_any(IrqChipSnapshot {
78 ioapic_state: self.get_ioapic_state()?,
79 lapic_state: lapics,
80 pic_state_1: self.get_pic_state(PicSelect::Primary)?,
81 pic_state_2: self.get_pic_state(PicSelect::Secondary)?,
82 pit_state: self.get_pit()?,
83 chip_specific_state: self.snapshot_chip_specific()?,
84 mp_state: mp_states,
85 })
86 .context("failed to serialize KvmKernelIrqChip")
87 }
88
89 fn restore(&self, data: AnySnapshot, vcpus_num: usize) -> anyhow::Result<()> {
91 let deser: IrqChipSnapshot =
92 AnySnapshot::from_any(data).context("failed to deserialize data")?;
93
94 if deser.lapic_state.len() != vcpus_num {
95 return Err(anyhow!(
96 "IrqChip has the wrong number of LAPIC state snapshots: got {}, expected {}",
97 deser.lapic_state.len(),
98 vcpus_num
99 ));
100 }
101 let supports_mp_states = self.check_capability(IrqChipCap::MpStateGetSet);
102
103 if supports_mp_states {
104 if deser.mp_state.len() != vcpus_num {
105 return Err(anyhow!(
106 "IrqChip has the wrong number of mp state snapshots: got {}, expected {}",
107 deser.mp_state.len(),
108 vcpus_num
109 ));
110 }
111 } else if !deser.mp_state.is_empty() {
112 return Err(anyhow!(
113 "IrqChip does not support mp state, but mp state was in the snapshot"
114 ));
115 }
116
117 self.set_pit(&deser.pit_state)?;
118 self.set_pic_state(PicSelect::Primary, &deser.pic_state_1)
119 .context("failed to set primary PIC")?;
120 self.set_pic_state(PicSelect::Secondary, &deser.pic_state_2)
121 .context("failed to set secondary PIC")?;
122 self.set_ioapic_state(&deser.ioapic_state)
123 .context("failed to set IOAPIC state")?;
124 self.restore_chip_specific(deser.chip_specific_state)
125 .context("failed to set chip specific data")?;
126 for (i, lapic) in deser.lapic_state.iter().enumerate() {
127 self.set_lapic_state(i, lapic)
128 .context("failed to set LAPIC state")?;
129 }
130
131 if supports_mp_states {
132 for (i, mp_state) in deser.mp_state.iter().enumerate() {
133 self.set_mp_state(i, mp_state)
134 .context("failed to set mp state")?;
135 }
136 }
137 Ok(())
138 }
139}
140
141#[derive(Serialize, Deserialize)]
142struct IrqChipSnapshot {
143 ioapic_state: IoapicState,
144 lapic_state: Vec<LapicState>,
145 pic_state_1: PicState,
146 pic_state_2: PicState,
147 pit_state: PitState,
148 chip_specific_state: AnySnapshot,
149 mp_state: Vec<MPState>,
150}
151
152pub struct Routes {
154 routes: Vec<Vec<IrqSource>>,
160}
161
162impl Routes {
163 pub fn new() -> Self {
165 Routes { routes: vec![] }
166 }
167
168 pub fn add(&mut self, route: IrqRoute) -> Result<()> {
173 let routes = self.get_mut(route.gsi as usize);
174 if routes.iter().any(|r| !Self::same_source(&route.source, r)) {
175 return Err(Error::new(libc::EINVAL));
180 }
181 routes.retain(|r| !Self::conflict(&route.source, r));
182 routes.push(route.source);
183 Ok(())
184 }
185
186 pub fn replace_all(&mut self, routes: &[IrqRoute]) -> Result<()> {
189 self.routes.clear();
190 for r in routes {
191 self.add(*r)?;
192 }
193 Ok(())
194 }
195
196 pub fn default_pic_ioapic_routes(ioapic_pins: usize) -> Vec<IrqRoute> {
199 let mut routes: Vec<IrqRoute> = Vec::new();
200
201 for i in 0..8 {
202 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicPrimary, i));
203 routes.push(IrqRoute::ioapic_irq_route(i));
204 }
205 for i in 8..16 {
206 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicSecondary, i));
207 routes.push(IrqRoute::ioapic_irq_route(i));
208 }
209 for i in 16..ioapic_pins as u32 {
210 routes.push(IrqRoute::ioapic_irq_route(i));
211 }
212
213 routes
214 }
215
216 pub fn get_routes(&self) -> Vec<IrqRoute> {
218 let mut routes = Vec::with_capacity(self.routes.len());
219 for (gsi, sources) in self.routes.iter().enumerate() {
220 for source in sources.iter() {
221 routes.push(IrqRoute {
222 gsi: gsi.try_into().expect("GSIs must be < u32::MAX"),
223 source: *source,
224 });
225 }
226 }
227 routes
228 }
229
230 fn conflict(source: &IrqSource, other: &IrqSource) -> bool {
233 use IrqSource::*;
234
235 if let (Msi { .. }, Msi { .. }) = (source, other) {
237 return true;
238 }
239
240 if let (
242 Irqchip { chip, .. },
243 Irqchip {
244 chip: other_chip, ..
245 },
246 ) = (source, other)
247 {
248 return chip == other_chip;
249 }
250
251 false
253 }
254
255 fn same_source(source: &IrqSource, other: &IrqSource) -> bool {
258 use IrqSource::*;
259 matches!(
260 (source, other),
261 (Irqchip { .. }, Irqchip { .. }) | (Msi { .. }, Msi { .. })
262 )
263 }
264
265 fn get_mut(&mut self, irq: usize) -> &mut Vec<IrqSource> {
268 if irq >= self.routes.len() {
269 self.routes.resize_with(irq + 1, Vec::new);
270 }
271 self.routes.get_mut(irq).unwrap()
272 }
273}
274
275impl Default for Routes {
276 fn default() -> Self {
277 Self::new()
278 }
279}
280
281const EMPTY_ROUTE: [IrqSource; 0] = [];
282
283impl Index<usize> for Routes {
284 type Output = [IrqSource];
285
286 fn index(&self, irq: usize) -> &Self::Output {
288 if irq < self.routes.len() {
289 self.routes[irq].as_slice()
290 } else {
291 &EMPTY_ROUTE
292 }
293 }
294}
295
296pub(super) struct DelayedIoApicIrqEvents {
297 pub events: Vec<usize>,
300 pub trigger: Event,
302}
303
304impl DelayedIoApicIrqEvents {
305 pub fn new() -> Result<Self> {
306 Ok(DelayedIoApicIrqEvents {
307 events: Vec::new(),
308 trigger: Event::new()?,
309 })
310 }
311}