From 9f025e829ab6ed468cfb51d72ac105624afc3851 Mon Sep 17 00:00:00 2001 From: johannst Date: Thu, 1 Jul 2021 23:11:14 +0200 Subject: added support to query caps on kvm fd + few caps --- src/cap.rs | 34 ++++++++++++++++++++++++++++++++++ src/kvm.rs | 23 ++++++++++++++++++++++- src/lib.rs | 3 ++- sysdeps/kvm.c | 26 ++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/cap.rs diff --git a/src/cap.rs b/src/cap.rs new file mode 100644 index 0000000..672ca75 --- /dev/null +++ b/src/cap.rs @@ -0,0 +1,34 @@ +//! Definitions of KVM capabilities. + +use crate::kvm_sys; +use std::convert::Into; + +/// Definition of capabilities that return a bool value indicating whether the capability is +/// supported or not. +#[repr(u64)] +pub enum CapBool { + /// Check if capabilities can be queried on VM fds (`KVM_CAP_CHECK_EXTENSION_VM`). + CheckExtensionVm = kvm_sys::KVM_CAP_CHECK_EXTENSION_VM, +} + +impl Into for CapBool { + fn into(self) -> u64 { + self as u64 + } +} + +/// Definition of capabilities that return an integer value indicating the amount of the queried +/// capability. +#[repr(u64)] +pub enum CapInt { + /// Get the recommended max VPCUs (`KVM_CAP_NR_VCPUS`). + NrVcpus = kvm_sys::KVM_CAP_NR_VCPUS, + /// Get the possible max VPCUs (`KVM_CAP_MAX_VCPUS`). + MaxVcpus = kvm_sys::KVM_CAP_MAX_VCPUS, +} + +impl Into for CapInt { + fn into(self) -> u64 { + self as u64 + } +} diff --git a/src/kvm.rs b/src/kvm.rs index 23112aa..30a00bb 100644 --- a/src/kvm.rs +++ b/src/kvm.rs @@ -4,8 +4,9 @@ use std::fs; use std::io; use std::os::unix::io::FromRawFd; -use crate::{libcret, ioctl, kvm_sys}; +use crate::cap::{CapBool, CapInt}; use crate::vm::Vm; +use crate::{ioctl, kvm_sys, libcret}; /// Wrapper for `/dev/kvm` ioctls. /// @@ -49,4 +50,24 @@ impl Kvm { Ok(Vm::new(vm, vcpu_mmap_size)) } + + /// Check availability of an extension with the [`KVM_CHECK_EXTENSION`][kvm-check-extension] + /// ioctl. + /// + /// [kvm-check-extension]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-check-extension + pub fn check_extenstion(&self, cap: CapBool) -> bool { + let ret = ioctl(&self.kvm, kvm_sys::KVM_CHECK_EXTENSION, cap.into()); + + matches!(ret, Ok(ret) if ret > 0) + } + + /// Check availability of an extension with the [`KVM_CHECK_EXTENSION`][kvm-check-extension] + /// ioctl. + /// + /// [kvm-check-extension]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-check-extension + pub fn check_extenstion_int(&self, cap: CapInt) -> i32 { + let ret = ioctl(&self.kvm, kvm_sys::KVM_CHECK_EXTENSION, cap.into()); + + ret.unwrap_or(0) + } } diff --git a/src/lib.rs b/src/lib.rs index 1833890..372255c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ use std::io; use std::ops; use std::os::unix::io::AsRawFd; +pub mod cap; mod fmt; pub mod kvm; pub mod kvm_sys; @@ -154,7 +155,7 @@ impl ops::Drop for KvmRun { impl AsRef for KvmRun { fn as_ref(&self) -> &kvm_sys::kvm_run { - unsafe { & *(self.ptr as *const kvm_sys::kvm_run) } + unsafe { &*(self.ptr as *const kvm_sys::kvm_run) } } } diff --git a/sysdeps/kvm.c b/sysdeps/kvm.c index 1665349..f7ff1a4 100644 --- a/sysdeps/kvm.c +++ b/sysdeps/kvm.c @@ -56,6 +56,32 @@ int main() { printf("pub(crate) const KVM_EXIT_IO_OUT : u64 = 0x%x;\n", KVM_EXIT_IO_OUT); printf("pub(crate) const KVM_EXIT_MMIO : u64 = 0x%x;\n", KVM_EXIT_MMIO); + /* Capabilities */ + + // Can be used on /dev/kvm fd and VM fd (if KVM_CAP_CHECK_EXTENSION_VM is available). + // + // param: capability to query KVM_CAP_* + // ret : 0 unsupported, 1 supported (some return >=1 returning number for cap) + printf("pub(crate) const KVM_CHECK_EXTENSION : u64 = 0x%x;\n", KVM_CHECK_EXTENSION); + + /* Bool Capabilities */ + + // Check if capabilities can be checked in VM fd. + // + // ret: 0 unsupported, 1 supported + printf("pub(crate) const KVM_CAP_CHECK_EXTENSION_VM : u64 = 0x%x;\n", KVM_CAP_CHECK_EXTENSION_VM); + + /* Int Capabilities */ + + // Check the recommended max amount of VCPUs. + // + // ret: 0 unsupported, >0 #vcpus + printf("pub(crate) const KVM_CAP_NR_VCPUS : u64 = 0x%x;\n", KVM_CAP_NR_VCPUS); + // Check the possible max amount of VCPUs. + // + // ret: 0 unsupported, >0 #vcpus + printf("pub(crate) const KVM_CAP_MAX_VCPUS : u64 = 0x%x;\n", KVM_CAP_MAX_VCPUS); + /* Testing constants */ printf("#[cfg(test)] const TEST_KVM_REGS_SIZE : usize = %ld;\n", sizeof(struct kvm_regs)); -- cgit v1.2.3