Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kvm-ioctls/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Plumb through KVM_CAP_DIRTY_LOG_RING as DirtyLogRing cap.
- [[#359]](https://github.com/rust-vmm/kvm/pull/359) Add support for `KVM_SET_MSR_FILTER` vm ioctl on x86_64.
- Add support for `KVM_REINJECT_CONTROL` vm ioctl on x86_64, also a shortcut `disable_pit_reinjection` on `VmFd`.

## v0.24.0

Expand Down
78 changes: 78 additions & 0 deletions kvm-ioctls/src/ioctls/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,70 @@ impl VmFd {
}
}

/// Controls the PIT Reinjection feature.
///
/// # Arguments
///
/// * rejection_control - `kvm_pit_rejection_control` structure to enable/disable PIT reinjection.
///
/// # Example
/// ```rust
/// extern crate kvm_ioctls;
/// extern crate kvm_bindings;
/// use kvm_ioctls::Kvm;
/// use kvm_bindings::{kvm_reinject_control};
/// use kvm_bindings::kvm_pit_config;
/// let kvm = Kvm::new().unwrap();
/// let vm = kvm.create_vm().unwrap();
/// vm.create_irq_chip().unwrap();
/// let pit_config = kvm_pit_config::default();
/// vm.create_pit2(pit_config).unwrap();
///
/// let rejection_control = kvm_reinject_control {
/// pit_reinject: 0,
/// ..Default::default()
/// };
/// vm.control_pit_reinjection(rejection_control).unwrap();
#[cfg(target_arch = "x86_64")]
pub fn control_pit_reinjection(&self, rejection_control: kvm_reinject_control) -> Result<()> {
// SAFETY: Safe because we know that our file is a VM fd and we verify the return result.
let ret = unsafe { ioctl_with_ref(self, KVM_REINJECT_CONTROL(), &rejection_control) };
if ret == 0 {
Ok(())
} else {
Err(errno::Error::last())
}
}

/// Disable PIT reinjection.
///
/// # equivalent to calling `control_pit_reinjection` with `pit_reinject` set to 0.
///
/// # kernel doc recommend that this is always done unless the guest OS requires PIT
/// # to do reinjection.
///
/// # Example
/// ```rust
/// extern crate kvm_ioctls;
/// extern crate kvm_bindings;
/// use kvm_bindings::kvm_pit_config;
/// use kvm_ioctls::Kvm;
/// let kvm = Kvm::new().unwrap();
/// let vm = kvm.create_vm().unwrap();
/// vm.create_irq_chip().unwrap();
/// let pit_config = kvm_bindings::kvm_pit_config::default();
/// vm.create_pit2(pit_config).unwrap();
/// vm.disable_pit_reinjection().unwrap();
/// ```
#[cfg(target_arch = "x86_64")]
pub fn disable_pit_reinjection(&self) -> Result<()> {
let rejection_control = kvm_reinject_control {
pit_reinject: 0,
..Default::default()
};
self.control_pit_reinjection(rejection_control)
}

/// Creates a PIT as per the `KVM_CREATE_PIT2` ioctl.
///
/// # Arguments
Expand Down Expand Up @@ -2407,6 +2471,20 @@ mod tests {
assert_eq!(pit2, other_pit2);
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_disable_reinjection() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
vm.create_irq_chip().unwrap();
vm.create_pit2(kvm_pit_config::default()).unwrap();
let reinjection = kvm_reinject_control {
pit_reinject: 0,
..Default::default()
};
vm.control_pit_reinjection(reinjection).unwrap();
}

#[cfg(target_arch = "x86_64")]
#[test]
fn test_clock() {
Expand Down
3 changes: 3 additions & 0 deletions kvm-ioctls/src/kvm_ioctls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ ioctl_iow_nr!(
target_arch = "riscv64"
))]
ioctl_iow_nr!(KVM_SET_GSI_ROUTING, KVMIO, 0x6a, kvm_irq_routing);
/* Available with KVM_CAP_REINJECT_CONTROL */
#[cfg(target_arch = "x86_64")]
ioctl_io_nr!(KVM_REINJECT_CONTROL, KVMIO, 0x71);
/* Available with KVM_CAP_IRQFD */
#[cfg(any(
target_arch = "x86_64",
Expand Down