Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/tests/irqchip/x86_64.rs
5394 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#![cfg(target_arch = "x86_64")]
6
7
use devices::IrqChipX86_64;
8
use devices::Routes;
9
use hypervisor::IrqRoute;
10
use hypervisor::IrqSource;
11
use hypervisor::IrqSourceChip;
12
use hypervisor::PicSelect;
13
14
#[allow(unused)]
15
pub fn test_get_pic(mut chip: impl IrqChipX86_64) {
16
let state = chip
17
.get_pic_state(PicSelect::Primary)
18
.expect("could not get pic state");
19
20
// Default is that no irq lines are asserted
21
assert_eq!(state.irr, 0);
22
23
// Assert Irq Line 0
24
chip.service_irq(0, true).expect("could not service irq");
25
26
let state = chip
27
.get_pic_state(PicSelect::Primary)
28
.expect("could not get pic state");
29
30
// Bit 0 should now be 1
31
assert_eq!(state.irr, 1);
32
}
33
34
pub fn test_set_pic(mut chip: impl IrqChipX86_64) {
35
let mut state = chip
36
.get_pic_state(PicSelect::Primary)
37
.expect("could not get pic state");
38
39
// set bits 0 and 1
40
state.irr = 3;
41
42
chip.set_pic_state(PicSelect::Primary, &state)
43
.expect("could not set the pic state");
44
45
let state = chip
46
.get_pic_state(PicSelect::Primary)
47
.expect("could not get pic state");
48
49
// Bits 1 and 0 should now be 1
50
assert_eq!(state.irr, 3);
51
}
52
53
pub fn test_get_ioapic(mut chip: impl IrqChipX86_64) {
54
let state = chip.get_ioapic_state().expect("could not get ioapic state");
55
56
// Default is that no irq lines are asserted
57
assert_eq!(state.current_interrupt_level_bitmap, 0);
58
59
// Default routing entries has routes 0..24 routed to vectors 0..24
60
for i in 0..24 {
61
// when the ioapic is reset by kvm, it defaults to all zeroes except the
62
// interrupt mask is set to 1, which is bit 16
63
assert_eq!(state.redirect_table[i].get(0, 64), 1 << 16);
64
}
65
66
// Assert Irq Line 1
67
chip.service_irq(1, true).expect("could not set irq line");
68
69
let state = chip.get_ioapic_state().expect("could not get ioapic state");
70
71
// Bit 1 should now be 1
72
assert_eq!(state.current_interrupt_level_bitmap, 2);
73
}
74
75
pub fn test_set_ioapic(mut chip: impl IrqChipX86_64) {
76
let mut state = chip.get_ioapic_state().expect("could not get ioapic state");
77
78
// set a vector in the redirect table
79
state.redirect_table[2].set_vector(15);
80
// set the irq line status on that entry
81
state.current_interrupt_level_bitmap = 4;
82
83
chip.set_ioapic_state(&state)
84
.expect("could not set the ioapic state");
85
86
let state = chip.get_ioapic_state().expect("could not get ioapic state");
87
88
// verify that get_ioapic_state returns what we set
89
assert_eq!(state.redirect_table[2].get_vector(), 15);
90
assert_eq!(state.current_interrupt_level_bitmap, 4);
91
}
92
93
pub fn test_get_pit(chip: impl IrqChipX86_64) {
94
let state = chip.get_pit().expect("failed to get pit state");
95
96
assert_eq!(state.flags, 0);
97
// assert reset state of pit
98
for i in 0..3 {
99
// initial count of 0 sets it to 0x10000;
100
assert_eq!(state.channels[i].count, 0x10000);
101
}
102
}
103
104
pub fn test_set_pit(mut chip: impl IrqChipX86_64) {
105
let mut state = chip.get_pit().expect("failed to get pit state");
106
107
// set some values
108
state.channels[0].count = 500;
109
state.channels[0].mode = 1;
110
111
// Setting the pit should initialize the one-shot timer
112
chip.set_pit(&state).expect("failed to set pit state");
113
114
let state = chip.get_pit().expect("failed to get pit state");
115
116
// check the values we set
117
assert_eq!(state.channels[0].count, 500);
118
assert_eq!(state.channels[0].mode, 1);
119
}
120
121
#[allow(unused)]
122
pub fn test_get_lapic(chip: impl IrqChipX86_64) {
123
let state = chip.get_lapic_state(0).expect("failed to get lapic state");
124
125
// Checking some APIC reg defaults for KVM:
126
// DFR default is 0xffffffff
127
assert_eq!(state.regs[0xe], 0xffffffff);
128
// SPIV default is 0xff
129
assert_eq!(state.regs[0xf], 0xff);
130
}
131
132
#[allow(unused)]
133
pub fn test_set_lapic(mut chip: impl IrqChipX86_64) {
134
// Get default state
135
let mut state = chip.get_lapic_state(0).expect("failed to get lapic state");
136
137
// ESR should start out as 0
138
assert_eq!(state.regs[8], 0);
139
// Set a value in the ESR
140
state.regs[8] = 1 << 8;
141
chip.set_lapic_state(0, &state)
142
.expect("failed to set lapic state");
143
144
// check that new ESR value stuck
145
let state = chip.get_lapic_state(0).expect("failed to get lapic state");
146
assert_eq!(state.regs[8], 1 << 8);
147
}
148
149
/// Helper function for checking the pic interrupt status
150
fn check_pic_interrupts(chip: &impl IrqChipX86_64, select: PicSelect, value: u8) {
151
let state = chip
152
.get_pic_state(select)
153
.expect("could not get ioapic state");
154
155
assert_eq!(state.irr, value);
156
}
157
158
/// Helper function for checking the ioapic interrupt status
159
fn check_ioapic_interrupts(chip: &impl IrqChipX86_64, value: u32) {
160
let state = chip.get_ioapic_state().expect("could not get ioapic state");
161
162
// since the irq route goes nowhere the bitmap should still be 0
163
assert_eq!(state.current_interrupt_level_bitmap, value);
164
}
165
166
pub fn test_route_irq(mut chip: impl IrqChipX86_64) {
167
// clear out irq routes
168
chip.set_irq_routes(&[])
169
.expect("failed to set empty irq routes");
170
// assert Irq Line 1
171
chip.service_irq(1, true).expect("could not set irq line");
172
173
// no pic or ioapic interrupts should be asserted
174
check_pic_interrupts(&chip, PicSelect::Primary, 0);
175
check_ioapic_interrupts(&chip, 0);
176
177
// now we route gsi 1 to pin 3 of the ioapic and pin 6 of the primary pic
178
chip.route_irq(IrqRoute {
179
gsi: 1,
180
source: IrqSource::Irqchip {
181
chip: IrqSourceChip::Ioapic,
182
pin: 3,
183
},
184
})
185
.expect("failed to assert irq route");
186
// re-assert Irq Line 1
187
chip.service_irq(1, true).expect("could not set irq line");
188
189
// no pic line should be asserted, ioapic pin 3 should be asserted
190
check_pic_interrupts(&chip, PicSelect::Primary, 0);
191
check_ioapic_interrupts(&chip, 1 << 3);
192
193
// de-assert Irq Line 1
194
chip.service_irq(1, false).expect("could not set irq line");
195
196
// no pic or ioapic interrupts should be asserted
197
check_pic_interrupts(&chip, PicSelect::Primary, 0);
198
check_ioapic_interrupts(&chip, 0);
199
200
// add pic route
201
chip.route_irq(IrqRoute {
202
gsi: 2,
203
source: IrqSource::Irqchip {
204
chip: IrqSourceChip::PicPrimary,
205
pin: 6,
206
},
207
})
208
.expect("failed to route irq");
209
210
// re-assert Irq Line 1, it should still affect only the ioapic
211
chip.service_irq(1, true).expect("could not set irq line");
212
213
// no pic line should be asserted, ioapic pin 3 should be asserted
214
check_pic_interrupts(&chip, PicSelect::Primary, 0);
215
check_ioapic_interrupts(&chip, 1 << 3);
216
217
// assert Irq Line 2
218
chip.service_irq(2, true).expect("could not set irq line");
219
220
// pic pin 6 should be asserted, ioapic pin 3 should be asserted
221
check_pic_interrupts(&chip, PicSelect::Primary, 1 << 6);
222
check_ioapic_interrupts(&chip, 1 << 3);
223
}
224
225
#[test]
226
fn add_routes() {
227
let ioapic_pins = hypervisor::NUM_IOAPIC_PINS;
228
let mut r = Routes::new();
229
r.replace_all(&Routes::default_pic_ioapic_routes(ioapic_pins))
230
.unwrap();
231
232
assert_eq!(r[0].len(), 2);
233
234
assert_eq!(r[ioapic_pins - 1].len(), 1);
235
r.add(IrqRoute {
236
gsi: ioapic_pins as u32 - 1,
237
source: IrqSource::Irqchip {
238
chip: IrqSourceChip::Ioapic,
239
pin: 3,
240
},
241
})
242
.unwrap();
243
assert_eq!(r[ioapic_pins - 1].len(), 1);
244
r.add(IrqRoute {
245
gsi: ioapic_pins as u32 - 1,
246
source: IrqSource::Irqchip {
247
chip: IrqSourceChip::PicPrimary,
248
pin: 3,
249
},
250
})
251
.unwrap();
252
assert_eq!(r[ioapic_pins - 1].len(), 2);
253
assert!(r
254
.add(IrqRoute {
255
gsi: ioapic_pins as u32 - 1,
256
source: IrqSource::Msi {
257
address: 0,
258
data: 0,
259
},
260
})
261
.is_err(),);
262
assert_eq!(r[ioapic_pins - 1].len(), 2);
263
264
assert_eq!(r[ioapic_pins].len(), 0);
265
r.add(IrqRoute {
266
gsi: ioapic_pins as u32,
267
source: IrqSource::Msi {
268
address: 0,
269
data: 0,
270
},
271
})
272
.unwrap();
273
assert_eq!(r[ioapic_pins].len(), 1);
274
assert!(r
275
.add(IrqRoute {
276
gsi: ioapic_pins as u32,
277
source: IrqSource::Irqchip {
278
chip: IrqSourceChip::Ioapic,
279
pin: 3
280
},
281
})
282
.is_err(),);
283
assert_eq!(r[ioapic_pins].len(), 1);
284
285
assert_eq!(r[500].len(), 0);
286
}
287
288