Skip to content

Commit 533c85e

Browse files
juliusxlhjiangliu
authored andcommitted
unit test
Signed-off-by: 守情 <liheng.xlh@alibaba-inc.com>
1 parent d7a5d04 commit 533c85e

File tree

5 files changed

+485
-0
lines changed

5 files changed

+485
-0
lines changed

src/interrupt/kvm_irq/generic_msi.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,66 @@ pub(super) fn create_msi_routing_entries(
5656
}
5757
Ok(entries)
5858
}
59+
60+
#[cfg(test)]
61+
mod test {
62+
use super::*;
63+
64+
#[test]
65+
fn test_create_msiconfig() {
66+
let config = MsiConfig::new();
67+
config.irqfd.write(1).unwrap();
68+
}
69+
70+
#[test]
71+
fn test_new_msi_routing_single() {
72+
let test_gsi = 4;
73+
let msi_source_config = MsiIrqSourceConfig {
74+
high_addr: 0x1234,
75+
low_addr: 0x5678,
76+
data: 0x9876,
77+
};
78+
let entry = new_msi_routing_entry(test_gsi, &msi_source_config);
79+
assert_eq!(entry.gsi, test_gsi);
80+
assert_eq!(entry.type_, KVM_IRQ_ROUTING_MSI);
81+
unsafe {
82+
assert_eq!(entry.u.msi.address_hi, msi_source_config.high_addr);
83+
assert_eq!(entry.u.msi.address_lo, msi_source_config.low_addr);
84+
assert_eq!(entry.u.msi.data, msi_source_config.data);
85+
}
86+
}
87+
88+
#[test]
89+
fn test_new_msi_routing_multi() {
90+
let mut msi_fds = Vec::with_capacity(16);
91+
for _ in 0..16 {
92+
msi_fds.push(InterruptSourceConfig::MsiIrq(MsiIrqSourceConfig {
93+
high_addr: 0x1234,
94+
low_addr: 0x5678,
95+
data: 0x9876,
96+
}));
97+
}
98+
let mut legacy_fds = Vec::with_capacity(16);
99+
for _ in 0..16 {
100+
legacy_fds.push(InterruptSourceConfig::LegacyIrq(LegacyIrqSourceConfig {}));
101+
}
102+
103+
let base = 0;
104+
let entrys = create_msi_routing_entries(0, &msi_fds).unwrap();
105+
106+
for (i, entry) in entrys.iter().enumerate() {
107+
assert_eq!(entry.gsi, (base + i) as u32);
108+
assert_eq!(entry.type_, KVM_IRQ_ROUTING_MSI);
109+
if let InterruptSourceConfig::MsiIrq(config) = &msi_fds[i] {
110+
unsafe {
111+
assert_eq!(entry.u.msi.address_hi, config.high_addr);
112+
assert_eq!(entry.u.msi.address_lo, config.low_addr);
113+
assert_eq!(entry.u.msi.data, config.data);
114+
}
115+
}
116+
}
117+
118+
assert!(create_msi_routing_entries(0, &legacy_fds).is_err());
119+
assert!(create_msi_routing_entries(!0, &msi_fds).is_err());
120+
}
121+
}

src/interrupt/kvm_irq/legacy_irq.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,51 @@ impl InterruptSourceGroup for LegacyIrq {
115115
}
116116
}
117117
}
118+
119+
#[cfg(test)]
120+
mod test {
121+
use super::*;
122+
use kvm_ioctls::{Kvm, VmFd};
123+
124+
fn create_vm_fd() -> VmFd {
125+
let kvm = Kvm::new().unwrap();
126+
kvm.create_vm().unwrap()
127+
}
128+
129+
#[test]
130+
fn test_legacy_interrupt_group() {
131+
let vmfd = Arc::new(create_vm_fd());
132+
let rounting = Arc::new(KvmIrqRouting::new(vmfd.clone()));
133+
let base = 0;
134+
let count = 1;
135+
let group = LegacyIrq::new(base, count, vmfd.clone(), rounting.clone()).unwrap();
136+
137+
let mut legacy_fds = Vec::with_capacity(1);
138+
legacy_fds.push(InterruptSourceConfig::LegacyIrq(LegacyIrqSourceConfig {}));
139+
140+
match group.get_type() {
141+
InterruptSourceType::LegacyIrq => {}
142+
_ => {
143+
panic!();
144+
}
145+
}
146+
assert_eq!(group.len(), 1);
147+
assert_eq!(group.get_base(), base);
148+
assert!(group.enable(&legacy_fds).is_ok());
149+
assert!(group.get_irqfd(0).unwrap().write(1).is_ok());
150+
assert!(group.trigger(0, 0x168).is_ok());
151+
assert!(group.ack(0, 0x168).is_ok());
152+
assert!(group.trigger(1, 0x168).is_err());
153+
assert!(group.ack(1, 0x168).is_err());
154+
assert!(group
155+
.modify(
156+
0,
157+
&InterruptSourceConfig::LegacyIrq(LegacyIrqSourceConfig {})
158+
)
159+
.is_ok());
160+
assert!(group.disable().is_ok());
161+
162+
assert!(LegacyIrq::new(base, 2, vmfd.clone(), rounting.clone()).is_err());
163+
assert!(LegacyIrq::new(110, 1, vmfd.clone(), rounting.clone()).is_err());
164+
}
165+
}

src/interrupt/kvm_irq/mod.rs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,200 @@ impl KvmIrqRouting {
275275
Ok(())
276276
}
277277
}
278+
279+
#[cfg(test)]
280+
mod test {
281+
use super::*;
282+
use kvm_ioctls::{DeviceFd, Kvm, VmFd};
283+
use std::path::Path;
284+
use vfio_ioctls::{VfioContainer, VfioDevice};
285+
286+
const VFIO_PCI_MSI_IRQ_INDEX: u32 = 1;
287+
288+
fn create_vm_fd() -> VmFd {
289+
let kvm = Kvm::new().unwrap();
290+
kvm.create_vm().unwrap()
291+
}
292+
293+
fn create_kvm_device(vm: Arc<VmFd>) -> DeviceFd {
294+
let mut vfio_dev = kvm_bindings::kvm_create_device {
295+
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_VFIO,
296+
fd: 0,
297+
flags: 0,
298+
};
299+
300+
vm.create_device(&mut vfio_dev).unwrap()
301+
}
302+
303+
fn create_irq_group(
304+
manager: Arc<KvmIrqManager>,
305+
vmfd: Arc<VmFd>,
306+
) -> Arc<dyn InterruptSourceGroup> {
307+
let base = 0;
308+
let count = 1;
309+
310+
manager
311+
.create_group(InterruptSourceType::LegacyIrq, base, count)
312+
.unwrap()
313+
}
314+
315+
fn create_msi_group(
316+
manager: Arc<KvmIrqManager>,
317+
vmfd: Arc<VmFd>,
318+
) -> Arc<dyn InterruptSourceGroup> {
319+
let base = 168;
320+
let count = 32;
321+
322+
manager
323+
.create_group(InterruptSourceType::MsiIrq, base, count)
324+
.unwrap()
325+
}
326+
327+
fn create_vfio_msi_group(
328+
manager: Arc<KvmIrqManager>,
329+
vmfd: Arc<VmFd>,
330+
) -> Arc<dyn InterruptSourceGroup> {
331+
let kvm_device = create_kvm_device(vmfd.clone());
332+
let kvm_device = Arc::new(kvm_device);
333+
let sysfspath_eth1: &Path = Path::new("/sys/bus/pci/devices/0000:5c:00.0/");
334+
let container = Arc::new(VfioContainer::new(kvm_device).unwrap());
335+
let vfio_device = Arc::new(
336+
VfioDevice::new(sysfspath_eth1, container)
337+
.map_err(|err| println!("{}", err))
338+
.unwrap(),
339+
);
340+
341+
let count = match vfio_device.get_irq_info(VFIO_PCI_MSI_IRQ_INDEX) {
342+
Some(ref info) => info.count,
343+
None => 0,
344+
};
345+
346+
manager
347+
.create_group(
348+
InterruptSourceType::VfioMsiIrq(vfio_device, VFIO_PCI_MSI_IRQ_INDEX),
349+
0,
350+
count,
351+
)
352+
.unwrap()
353+
}
354+
355+
const MASTER_PIC: usize = 7;
356+
const SLAVE_PIC: usize = 8;
357+
const IOAPIC: usize = 23;
358+
359+
#[test]
360+
fn test_create_kvmirqmanager() {
361+
let vmfd = Arc::new(create_vm_fd());
362+
let manager = KvmIrqManager::new(vmfd.clone());
363+
assert!(vmfd.create_irq_chip().is_ok());
364+
assert!(manager.initialize().is_ok());
365+
}
366+
367+
#[test]
368+
fn test_kvmirqmanager_opt() {
369+
let vmfd = Arc::new(create_vm_fd());
370+
assert!(vmfd.create_irq_chip().is_ok());
371+
let manager = Arc::new(KvmIrqManager::new(vmfd.clone()));
372+
assert!(manager.initialize().is_ok());
373+
//irq
374+
let group = create_irq_group(manager.clone(), vmfd.clone());
375+
let tmp = group.clone();
376+
assert!(manager.destroy_group(group).is_ok());
377+
//msi
378+
let group = create_msi_group(manager.clone(), vmfd.clone());
379+
let tmp = group.clone();
380+
assert!(manager.destroy_group(group).is_ok());
381+
//vfio msi
382+
let group = create_vfio_msi_group(manager.clone(), vmfd.clone());
383+
let tmp = group.clone();
384+
assert!(manager.destroy_group(group).is_ok());
385+
}
386+
387+
#[test]
388+
fn test_irqrouting_initialize_legacy() {
389+
let vmfd = Arc::new(create_vm_fd());
390+
let routing = KvmIrqRouting::new(vmfd.clone());
391+
assert!(routing.initialize().is_err());
392+
assert!(vmfd.create_irq_chip().is_ok());
393+
assert!(routing.initialize().is_ok());
394+
let routes = &routing.routes.lock().unwrap();
395+
assert_eq!(routes.len(), MASTER_PIC + SLAVE_PIC + IOAPIC);
396+
}
397+
398+
#[test]
399+
fn test_routing_opt() {
400+
// pub(super) fn modify(&self, entry: &kvm_irq_routing_entry) -> Result<()> {
401+
let vmfd = Arc::new(create_vm_fd());
402+
let routing = KvmIrqRouting::new(vmfd.clone());
403+
assert!(routing.initialize().is_err());
404+
assert!(vmfd.create_irq_chip().is_ok());
405+
assert!(routing.initialize().is_ok());
406+
407+
let mut entry = kvm_irq_routing_entry {
408+
gsi: 8,
409+
type_: KVM_IRQ_ROUTING_IRQCHIP,
410+
..Default::default()
411+
};
412+
413+
// Safe because we are initializing all fields of the `irqchip` struct.
414+
unsafe {
415+
entry.u.irqchip.irqchip = 0;
416+
entry.u.irqchip.pin = 3;
417+
}
418+
419+
let entrys = vec![entry.clone()];
420+
421+
assert!(routing.modify(&entry).is_err());
422+
assert!(routing.add(&entrys).is_ok());
423+
unsafe {
424+
entry.u.irqchip.pin = 4;
425+
}
426+
assert!(routing.modify(&entry).is_ok());
427+
assert!(routing.remove(&entrys).is_ok());
428+
assert!(routing.modify(&entry).is_err());
429+
}
430+
431+
#[test]
432+
fn test_routing_commit() {
433+
let vmfd = Arc::new(create_vm_fd());
434+
let routing = KvmIrqRouting::new(vmfd.clone());
435+
436+
assert!(routing.initialize().is_err());
437+
assert!(vmfd.create_irq_chip().is_ok());
438+
assert!(routing.initialize().is_ok());
439+
440+
let mut entry = kvm_irq_routing_entry {
441+
gsi: 8,
442+
type_: KVM_IRQ_ROUTING_IRQCHIP,
443+
..Default::default()
444+
};
445+
unsafe {
446+
entry.u.irqchip.irqchip = 0;
447+
entry.u.irqchip.pin = 3;
448+
}
449+
450+
routing
451+
.routes
452+
.lock()
453+
.unwrap()
454+
.insert(hash_key(&entry), entry);
455+
let routes = routing.routes.lock().unwrap();
456+
assert!(routing.commit(&routes).is_ok());
457+
}
458+
459+
#[test]
460+
fn test_has_key() {
461+
let gsi = 4;
462+
let mut entry = kvm_irq_routing_entry {
463+
gsi,
464+
type_: KVM_IRQ_ROUTING_IRQCHIP,
465+
..Default::default()
466+
};
467+
// Safe because we are initializing all fields of the `irqchip` struct.
468+
unsafe {
469+
entry.u.irqchip.irqchip = KVM_IRQCHIP_PIC_MASTER;
470+
entry.u.irqchip.pin = gsi;
471+
}
472+
assert_eq!(hash_key(&entry), 0x0001_0000_0004);
473+
}
474+
}

src/interrupt/kvm_irq/msi_irq.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,70 @@ impl InterruptSourceGroup for MsiIrq {
145145
Ok(())
146146
}
147147
}
148+
149+
#[cfg(test)]
150+
mod test {
151+
use super::*;
152+
use kvm_ioctls::{Kvm, VmFd};
153+
154+
fn create_vm_fd() -> VmFd {
155+
let kvm = Kvm::new().unwrap();
156+
kvm.create_vm().unwrap()
157+
}
158+
159+
#[test]
160+
fn test_msi_interrupt_group() {
161+
let vmfd = Arc::new(create_vm_fd());
162+
assert!(vmfd.create_irq_chip().is_ok());
163+
164+
let rounting = Arc::new(KvmIrqRouting::new(vmfd.clone()));
165+
assert!(rounting.initialize().is_ok());
166+
167+
let base = 168;
168+
let count = 32;
169+
let group = MsiIrq::new(base, count, vmfd.clone(), rounting.clone()).unwrap();
170+
let mut msi_fds = Vec::with_capacity(count as usize);
171+
172+
match group.get_type() {
173+
InterruptSourceType::MsiIrq => {}
174+
_ => {
175+
panic!();
176+
}
177+
}
178+
179+
for _ in 0..count {
180+
let msi_source_config = MsiIrqSourceConfig {
181+
high_addr: 0x1234,
182+
low_addr: 0x5678,
183+
data: 0x9876,
184+
};
185+
msi_fds.push(InterruptSourceConfig::MsiIrq(msi_source_config));
186+
}
187+
188+
assert!(group.enable(&msi_fds).is_ok());
189+
assert_eq!(group.len(), count);
190+
assert_eq!(group.get_base(), base);
191+
192+
for i in 0..count {
193+
let msi_source_config = MsiIrqSourceConfig {
194+
high_addr: i + 0x1234,
195+
low_addr: i + 0x5678,
196+
data: i + 0x9876,
197+
};
198+
assert!(group.get_irqfd(i).unwrap().write(1).is_ok());
199+
assert!(group.trigger(i, 0x168).is_err());
200+
assert!(group.trigger(i, 0).is_ok());
201+
assert!(group.ack(i, 0x168).is_err());
202+
assert!(group.ack(i, 0).is_ok());
203+
assert!(group
204+
.modify(0, &InterruptSourceConfig::MsiIrq(msi_source_config))
205+
.is_ok());
206+
}
207+
assert!(group.trigger(33, 0x168).is_err());
208+
assert!(group.ack(33, 0x168).is_err());
209+
assert!(group.disable().is_ok());
210+
211+
assert!(MsiIrq::new(base, 33, vmfd.clone(), rounting.clone()).is_err());
212+
assert!(MsiIrq::new(1100, 1, vmfd.clone(), rounting.clone()).is_err());
213+
}
214+
}

0 commit comments

Comments
 (0)