Skip to content

Commit b968736

Browse files
michael2012zandreeaflorescu
authored andcommitted
Add support for KVM_HAS_DEVICE_ATTR ioctl.
Following modifications are included: 1. Add the wrapper for KVM_HAS_DEVICE_ATTR ioctl. 2. Update the test case of VGIC. 3. Add an example to show the usage of KVM_HAS_DEVICE_ATTR together with KVM_SET_DEVICE_ATTR. Change-Id: Idacae319c8ff5ace722e81a279560d823e2458cc Signed-off-by: Michael Zhao <[email protected]>
1 parent 8303546 commit b968736

File tree

4 files changed

+80
-15
lines changed

4 files changed

+80
-15
lines changed

coverage_config_aarch64.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 76.3,
2+
"coverage_score": 76.5,
33
"exclude_path": "",
44
"crate_features": ""
55
}

coverage_config_x86_64.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 92.1,
2+
"coverage_score": 92.0,
33
"exclude_path": "",
44
"crate_features": ""
55
}

src/ioctls/device.rs

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
66

77
use ioctls::Result;
88
use kvm_bindings::kvm_device_attr;
9-
use kvm_ioctls::KVM_SET_DEVICE_ATTR;
9+
use kvm_ioctls::{KVM_HAS_DEVICE_ATTR, KVM_SET_DEVICE_ATTR};
1010
use vmm_sys_util::errno;
1111
use vmm_sys_util::ioctl::ioctl_with_ref;
1212

@@ -16,13 +16,63 @@ pub struct DeviceFd {
1616
}
1717

1818
impl DeviceFd {
19+
/// Tests whether a device supports a particular attribute.
20+
///
21+
/// See the documentation for `KVM_HAS_DEVICE_ATTR`.
22+
/// # Arguments
23+
///
24+
/// * `device_attr` - The device attribute to be tested. `addr` field is ignored.
25+
///
26+
pub fn has_device_attr(&self, device_attr: &kvm_device_attr) -> Result<()> {
27+
let ret = unsafe { ioctl_with_ref(self, KVM_HAS_DEVICE_ATTR(), device_attr) };
28+
if ret != 0 {
29+
return Err(errno::Error::last());
30+
}
31+
Ok(())
32+
}
33+
1934
/// Sets a specified piece of device configuration and/or state.
2035
///
2136
/// See the documentation for `KVM_SET_DEVICE_ATTR`.
2237
/// # Arguments
2338
///
2439
/// * `device_attr` - The device attribute to be set.
2540
///
41+
/// # Example
42+
///
43+
/// ```rust
44+
/// # extern crate kvm_ioctls;
45+
/// # extern crate kvm_bindings;
46+
/// # use kvm_ioctls::Kvm;
47+
/// # use kvm_bindings::{
48+
/// kvm_device_type_KVM_DEV_TYPE_VFIO,
49+
/// KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD, KVM_CREATE_DEVICE_TEST
50+
/// };
51+
/// let kvm = Kvm::new().unwrap();
52+
/// let vm = kvm.create_vm().unwrap();
53+
///
54+
/// let mut device = kvm_bindings::kvm_create_device {
55+
/// type_: kvm_device_type_KVM_DEV_TYPE_VFIO,
56+
/// fd: 0,
57+
/// flags: KVM_CREATE_DEVICE_TEST,
58+
/// };
59+
///
60+
/// let device_fd = vm
61+
/// .create_device(&mut device)
62+
/// .expect("Cannot create KVM device");
63+
///
64+
/// let dist_attr = kvm_bindings::kvm_device_attr {
65+
/// group: KVM_DEV_VFIO_GROUP,
66+
/// attr: u64::from(KVM_DEV_VFIO_GROUP_ADD),
67+
/// addr: 0x0,
68+
/// flags: 0,
69+
/// };
70+
///
71+
/// if (device_fd.has_device_attr(&dist_attr).is_ok()) {
72+
/// device_fd.set_device_attr(&dist_attr).unwrap();
73+
/// }
74+
/// ```
75+
///
2676
pub fn set_device_attr(&self, device_attr: &kvm_device_attr) -> Result<()> {
2777
let ret = unsafe { ioctl_with_ref(self, KVM_SET_DEVICE_ATTR(), device_attr) };
2878
if ret != 0 {
@@ -62,8 +112,15 @@ mod tests {
62112
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
63113
use kvm_bindings::{
64114
kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, kvm_device_type_KVM_DEV_TYPE_VFIO,
115+
KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD,
65116
};
66-
use kvm_bindings::{KVM_CREATE_DEVICE_TEST, KVM_DEV_VFIO_GROUP, KVM_DEV_VFIO_GROUP_ADD};
117+
#[cfg(target_arch = "aarch64")]
118+
use kvm_bindings::{
119+
KVM_DEV_ARM_VGIC_CTRL_INIT, KVM_DEV_ARM_VGIC_GRP_CTRL, KVM_DEV_VFIO_GROUP,
120+
KVM_DEV_VFIO_GROUP_ADD,
121+
};
122+
123+
use kvm_bindings::KVM_CREATE_DEVICE_TEST;
67124

68125
#[test]
69126
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -100,6 +157,7 @@ mod tests {
100157

101158
// We are just creating a test device. Creating a real device would make the CI dependent
102159
// on host configuration (like having /dev/vfio). We expect this to fail.
160+
assert!(device_fd.has_device_attr(&dist_attr).is_err());
103161
assert!(device_fd.set_device_attr(&dist_attr).is_err());
104162
assert_eq!(errno::Error::last().errno(), 25);
105163
}
@@ -118,31 +176,36 @@ mod tests {
118176
fd: 0,
119177
flags: KVM_CREATE_DEVICE_TEST,
120178
};
121-
// This fails on aarch64 as it does not use MPIC (MultiProcessor Interrupt Controller), it uses
122-
// the VGIC.
179+
// This fails on aarch64 as it does not use MPIC (MultiProcessor Interrupt Controller),
180+
// it uses the VGIC.
123181
assert!(vm.create_device(&mut gic_device).is_err());
124182

125-
let device_fd = create_gic_device(&vm, KVM_CREATE_DEVICE_TEST);
183+
let device_fd = create_gic_device(&vm, 0);
126184

127185
// Following lines to re-construct device_fd are used to test
128186
// DeviceFd::from_raw_fd() and DeviceFd::as_raw_fd().
129187
let raw_fd = unsafe { libc::dup(device_fd.as_raw_fd()) };
130188
assert!(raw_fd >= 0);
131189
let device_fd = unsafe { DeviceFd::from_raw_fd(raw_fd) };
132190

191+
// Set some attribute that does not apply to VGIC, expect the test to fail.
133192
let dist_attr = kvm_bindings::kvm_device_attr {
134193
group: KVM_DEV_VFIO_GROUP,
135194
attr: u64::from(KVM_DEV_VFIO_GROUP_ADD),
136195
addr: 0x0,
137196
flags: 0,
138197
};
198+
assert!(device_fd.has_device_attr(&dist_attr).is_err());
139199

140-
// We are just creating a test device. Creating a real device would make the CI dependent
141-
// on host configuration (like having /dev/vfio). We expect this to fail.
142-
assert!(device_fd.set_device_attr(&dist_attr).is_err());
143-
// Comment this assertion as a workaround for arm coverage test CI, as it is testing the error
144-
// case that cannot be reproduced in a real case scenario. This assertion will lead to failure
145-
// caused by ioctl returning `EINVAL` instead of `ENOTTY` when using gnu toolchain.
146-
//assert_eq!(errno::Error::last().errno(), 25);
200+
// Following attribute works with VGIC, they should be accepted.
201+
let dist_attr = kvm_bindings::kvm_device_attr {
202+
group: KVM_DEV_ARM_VGIC_GRP_CTRL,
203+
attr: u64::from(KVM_DEV_ARM_VGIC_CTRL_INIT),
204+
addr: 0x0,
205+
flags: 0,
206+
};
207+
208+
assert!(device_fd.has_device_attr(&dist_attr).is_ok());
209+
assert!(device_fd.set_device_attr(&dist_attr).is_ok());
147210
}
148211
}

src/kvm_ioctls.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,10 @@ ioctl_ior_nr!(KVM_ARM_PREFERRED_TARGET, KVMIO, 0xaf, kvm_vcpu_init);
216216

217217
/* Available with KVM_CAP_DEVICE_CTRL */
218218
ioctl_iowr_nr!(KVM_CREATE_DEVICE, KVMIO, 0xe0, kvm_create_device);
219-
/* Available with KVM_CAP_VM_ATTRIBUTES */
219+
/* Available with KVM_CAP_DEVICE_CTRL */
220220
ioctl_iow_nr!(KVM_SET_DEVICE_ATTR, KVMIO, 0xe1, kvm_device_attr);
221+
/* Available with KVM_CAP_DEVICE_CTRL */
222+
ioctl_iow_nr!(KVM_HAS_DEVICE_ATTR, KVMIO, 0xe3, kvm_device_attr);
221223

222224
#[cfg(test)]
223225
mod tests {

0 commit comments

Comments
 (0)