Skip to content

Commit a638005

Browse files
rbradfordSamuel Ortiz
authored andcommitted
ioctls: vcpu: Expose KVM_ENABLE_CAP for vCPU
Mirror the availability of the KVM_ENABLE_CAP ioctl() for the VM file descriptor to the vCPU file descriptor. Signed-off-by: Rob Bradford <[email protected]>
1 parent 782cdcb commit a638005

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

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": 91.2,
2+
"coverage_score": 91.1,
33
"exclude_path": "",
44
"crate_features": ""
55
}

src/ioctls/vcpu.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,52 @@ impl VcpuFd {
387387
Ok(cpuid)
388388
}
389389

390+
///
391+
/// See the documentation for `KVM_ENABLE_CAP`.
392+
///
393+
/// # Arguments
394+
///
395+
/// * kvm_enable_cap - KVM capability structure. For details check the `kvm_enable_cap`
396+
/// structure in the
397+
/// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
398+
///
399+
/// # Example
400+
///
401+
/// ```rust
402+
/// # extern crate kvm_ioctls;
403+
/// # extern crate kvm_bindings;
404+
/// # use kvm_bindings::{kvm_enable_cap, KVM_MAX_CPUID_ENTRIES, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP};
405+
/// # use kvm_ioctls::{Kvm, Cap};
406+
/// let kvm = Kvm::new().unwrap();
407+
/// let vm = kvm.create_vm().unwrap();
408+
/// let mut cap: kvm_enable_cap = Default::default();
409+
/// if cfg!(target_arch = "x86") || cfg!(target_arch = "x86_64") {
410+
/// // KVM_CAP_HYPERV_SYNIC needs KVM_CAP_SPLIT_IRQCHIP enabled
411+
/// cap.cap = KVM_CAP_SPLIT_IRQCHIP;
412+
/// cap.args[0] = 24;
413+
/// vm.enable_cap(&cap).unwrap();
414+
///
415+
/// let vcpu = vm.create_vcpu(0).unwrap();
416+
/// if kvm.check_extension(Cap::HypervSynic) {
417+
/// let mut cap: kvm_enable_cap = Default::default();
418+
/// cap.cap = KVM_CAP_HYPERV_SYNIC;
419+
/// vcpu.enable_cap(&cap).unwrap();
420+
/// }
421+
/// }
422+
/// ```
423+
///
424+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
425+
pub fn enable_cap(&self, cap: &kvm_enable_cap) -> Result<()> {
426+
// The ioctl is safe because we allocated the struct and we know the
427+
// kernel will write exactly the size of the struct.
428+
let ret = unsafe { ioctl_with_ref(self, KVM_ENABLE_CAP(), cap) };
429+
if ret == 0 {
430+
Ok(())
431+
} else {
432+
Err(errno::Error::last())
433+
}
434+
}
435+
390436
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
391437
///
392438
/// The state is returned in a `kvm_lapic_state` structure as defined in the
@@ -2007,4 +2053,23 @@ mod tests {
20072053
vcpu.set_kvm_immediate_exit(1);
20082054
assert_eq!(vcpu.kvm_run_ptr.as_mut_ref().immediate_exit, 1);
20092055
}
2056+
2057+
#[test]
2058+
#[cfg(target_arch = "x86_64")]
2059+
fn test_enable_cap() {
2060+
let kvm = Kvm::new().unwrap();
2061+
let vm = kvm.create_vm().unwrap();
2062+
let mut cap: kvm_enable_cap = Default::default();
2063+
// KVM_CAP_HYPERV_SYNIC needs KVM_CAP_SPLIT_IRQCHIP enabled
2064+
cap.cap = KVM_CAP_SPLIT_IRQCHIP;
2065+
cap.args[0] = 24;
2066+
vm.enable_cap(&cap).unwrap();
2067+
2068+
let vcpu = vm.create_vcpu(0).unwrap();
2069+
if kvm.check_extension(Cap::HypervSynic) {
2070+
let mut cap: kvm_enable_cap = Default::default();
2071+
cap.cap = KVM_CAP_HYPERV_SYNIC;
2072+
vcpu.enable_cap(&cap).unwrap();
2073+
}
2074+
}
20102075
}

0 commit comments

Comments
 (0)