Skip to content

Commit b7eadd8

Browse files
MrXinWangalxiord
authored andcommitted
Add unit tests for handling irqfd on aarch64
1. Added Unit tests for register and unregister irqfd on aarch64. 2. Added the new function create_gic_device which is used for removing duplicated code when creating GIC devices. Signed-off-by: Henry Wang <[email protected]>
1 parent 9a15cb0 commit b7eadd8

File tree

2 files changed

+77
-48
lines changed

2 files changed

+77
-48
lines changed

src/ioctls/device.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ impl FromRawFd for DeviceFd {
5959
mod tests {
6060
use super::*;
6161
use ioctls::system::Kvm;
62-
#[cfg(target_arch = "aarch64")]
63-
use kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2;
6462
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
65-
use kvm_bindings::kvm_device_type_KVM_DEV_TYPE_VFIO;
6663
use kvm_bindings::{
67-
kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, KVM_CREATE_DEVICE_TEST, KVM_DEV_VFIO_GROUP,
68-
KVM_DEV_VFIO_GROUP_ADD,
64+
kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, kvm_device_type_KVM_DEV_TYPE_VFIO,
6965
};
66+
use kvm_bindings::{KVM_CREATE_DEVICE_TEST, KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD};
7067

7168
#[test]
7269
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -110,6 +107,7 @@ mod tests {
110107
#[test]
111108
#[cfg(target_arch = "aarch64")]
112109
fn test_create_device() {
110+
use ioctls::vm::create_gic_device;
113111
use kvm_bindings::kvm_device_type_KVM_DEV_TYPE_FSL_MPIC_20;
114112

115113
let kvm = Kvm::new().unwrap();
@@ -124,16 +122,7 @@ mod tests {
124122
// the VGIC.
125123
assert!(vm.create_device(&mut gic_device).is_err());
126124

127-
gic_device.type_ = kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3;
128-
129-
let device_fd = match vm.create_device(&mut gic_device) {
130-
Ok(fd) => fd,
131-
Err(_) => {
132-
gic_device.type_ = kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2;
133-
vm.create_device(&mut gic_device)
134-
.expect("Cannot create KVM device")
135-
}
136-
};
125+
let device_fd = create_gic_device(&vm, KVM_CREATE_DEVICE_TEST);
137126

138127
// Following lines to re-construct device_fd are used to test
139128
// DeviceFd::from_raw_fd() and DeviceFd::as_raw_fd().

src/ioctls/vm.rs

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,32 @@ impl AsRawFd for VmFd {
11061106
}
11071107
}
11081108

1109+
/// Creates a dummy GIC device.
1110+
///
1111+
/// # Arguments
1112+
///
1113+
/// * `vm` - The vm file descriptor.
1114+
/// * `flags` - Flags to be passed to `KVM_CREATE_DEVICE`.
1115+
///
1116+
#[cfg(test)]
1117+
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
1118+
pub(crate) fn create_gic_device(vm: &VmFd, flags: u32) -> DeviceFd {
1119+
let mut gic_device = kvm_bindings::kvm_create_device {
1120+
type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3,
1121+
fd: 0,
1122+
flags,
1123+
};
1124+
let device_fd = match vm.create_device(&mut gic_device) {
1125+
Ok(fd) => fd,
1126+
Err(_) => {
1127+
gic_device.type_ = kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2;
1128+
vm.create_device(&mut gic_device)
1129+
.expect("Cannot create KVM vGIC device")
1130+
}
1131+
};
1132+
device_fd
1133+
}
1134+
11091135
#[cfg(test)]
11101136
mod tests {
11111137
use super::*;
@@ -1258,62 +1284,76 @@ mod tests {
12581284
}
12591285

12601286
#[test]
1261-
#[cfg(any(
1262-
target_arch = "x86",
1263-
target_arch = "x86_64",
1264-
target_arch = "arm",
1265-
target_arch = "aarch64"
1266-
))]
1267-
fn test_register_irqfd() {
1287+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1288+
fn test_register_unregister_irqfd() {
12681289
let kvm = Kvm::new().unwrap();
12691290
let vm_fd = kvm.create_vm().unwrap();
12701291
let evtfd1 = EventFd::new(EFD_NONBLOCK).unwrap();
12711292
let evtfd2 = EventFd::new(EFD_NONBLOCK).unwrap();
12721293
let evtfd3 = EventFd::new(EFD_NONBLOCK).unwrap();
1273-
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
1274-
assert!(vm_fd.create_irq_chip().is_ok());
1275-
assert!(vm_fd.register_irqfd(&evtfd1, 4).is_ok());
1276-
assert!(vm_fd.register_irqfd(&evtfd2, 8).is_ok());
1277-
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_ok());
1278-
}
12791294

1280-
// On aarch64, this fails because setting up the interrupt controller is mandatory before
1281-
// registering any IRQ.
1295+
assert!(vm_fd.create_irq_chip().is_ok());
1296+
1297+
assert!(vm_fd.register_irqfd(&evtfd1, 4).is_ok());
1298+
assert!(vm_fd.register_irqfd(&evtfd2, 8).is_ok());
1299+
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_ok());
1300+
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
1301+
// KVM irqfd doesn't report failure on this case:(
1302+
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
1303+
1304+
// Duplicated eventfd registration.
12821305
// On x86_64 this fails as the event fd was already matched with a GSI.
12831306
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_err());
12841307
assert!(vm_fd.register_irqfd(&evtfd3, 5).is_err());
1308+
// KVM irqfd doesn't report failure on this case:(
1309+
assert!(vm_fd.unregister_irqfd(&evtfd3, 5).is_ok());
12851310
}
12861311

12871312
#[test]
1288-
#[cfg(any(
1289-
target_arch = "x86",
1290-
target_arch = "x86_64",
1291-
target_arch = "arm",
1292-
target_arch = "aarch64"
1293-
))]
1294-
fn test_unregister_irqfd() {
1313+
#[cfg(target_arch = "aarch64")]
1314+
fn test_register_unregister_irqfd() {
12951315
let kvm = Kvm::new().unwrap();
12961316
let vm_fd = kvm.create_vm().unwrap();
12971317
let evtfd1 = EventFd::new(EFD_NONBLOCK).unwrap();
12981318
let evtfd2 = EventFd::new(EFD_NONBLOCK).unwrap();
12991319
let evtfd3 = EventFd::new(EFD_NONBLOCK).unwrap();
1300-
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
1301-
assert!(vm_fd.create_irq_chip().is_ok());
1302-
assert!(vm_fd.register_irqfd(&evtfd1, 4).is_ok());
1303-
assert!(vm_fd.register_irqfd(&evtfd2, 8).is_ok());
1304-
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_ok());
1305-
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
1306-
// KVM irqfd doesn't report failure on this case:(
1307-
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
1308-
}
1320+
1321+
// Create the vGIC device.
1322+
let vgic_fd = create_gic_device(&vm_fd, 0);
1323+
1324+
// Dummy interrupt for testing on aarch64.
1325+
let nr_irqs: u32 = 128;
1326+
1327+
// We need to tell the kernel how many irqs to support with this vgic.
1328+
let vgic_attr = kvm_bindings::kvm_device_attr {
1329+
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
1330+
attr: 0,
1331+
addr: &nr_irqs as *const u32 as u64,
1332+
flags: 0,
1333+
};
1334+
assert!(vgic_fd.set_device_attr(&vgic_attr).is_ok());
1335+
1336+
// Finalize the GIC.
1337+
let vgic_attr = kvm_bindings::kvm_device_attr {
1338+
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
1339+
attr: u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
1340+
addr: 0,
1341+
flags: 0,
1342+
};
1343+
assert!(vgic_fd.set_device_attr(&vgic_attr).is_ok());
1344+
1345+
assert!(vm_fd.register_irqfd(&evtfd1, 4).is_ok());
1346+
assert!(vm_fd.register_irqfd(&evtfd2, 8).is_ok());
1347+
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_ok());
1348+
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
1349+
// KVM irqfd doesn't report failure on this case:(
1350+
assert!(vm_fd.unregister_irqfd(&evtfd2, 8).is_ok());
13091351

13101352
// Duplicated eventfd registration.
13111353
// On aarch64, this fails because setting up the interrupt controller is mandatory before
13121354
// registering any IRQ.
1313-
// On x86_64 this fails as the event fd was already matched with a GSI.
13141355
assert!(vm_fd.register_irqfd(&evtfd3, 4).is_err());
13151356
assert!(vm_fd.register_irqfd(&evtfd3, 5).is_err());
1316-
13171357
// KVM irqfd doesn't report failure on this case:(
13181358
assert!(vm_fd.unregister_irqfd(&evtfd3, 5).is_ok());
13191359
}

0 commit comments

Comments
 (0)