aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kvm.rs13
-rw-r--r--src/kvm_sys.rs4
-rw-r--r--src/vcpu.rs36
-rw-r--r--src/vm.rs26
-rw-r--r--src/x86_64.rs8
5 files changed, 86 insertions, 1 deletions
diff --git a/src/kvm.rs b/src/kvm.rs
index 3522adc..23112aa 100644
--- a/src/kvm.rs
+++ b/src/kvm.rs
@@ -1,3 +1,5 @@
+//! KVM system ioctls.
+
use std::fs;
use std::io;
use std::os::unix::io::FromRawFd;
@@ -5,11 +7,18 @@ use std::os::unix::io::FromRawFd;
use crate::{libcret, ioctl, kvm_sys};
use crate::vm::Vm;
+/// Wrapper for `/dev/kvm` ioctls.
+///
+/// Representation of the file descriptor obtained by opening `/dev/kvm`.
+/// This wrapper provides access to the `system ioctls` as described in [KVM API][kvm].
+///
+/// [kvm]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#general-description
pub struct Kvm {
kvm: fs::File,
}
impl Kvm {
+ /// Open the `/dev/kvm` device.
pub fn new() -> io::Result<Kvm> {
let kvm = libcret(unsafe {
libc::open("/dev/kvm\0".as_ptr().cast(), libc::O_RDWR | libc::O_CLOEXEC)
@@ -28,6 +37,10 @@ impl Kvm {
ioctl(&self.kvm, kvm_sys::KVM_GET_VCPU_MMAP_SIZE, 0).map(|size| size as usize)
}
+ /// Create a new virtual machine with the [`KVM_CREATE_VM`][kvm-create-vm] ioctl.
+ /// Returns a wrapper [`vm::Vm`][crate::vm::Vm] representing the VM.
+ ///
+ /// [kvm-create-vm]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-create-vm
pub fn create_vm(&self) -> io::Result<Vm> {
let vm = ioctl(&self.kvm, kvm_sys::KVM_CREATE_VM, 0 /* machine id */)
.map(|fd| unsafe { fs::File::from_raw_fd(fd) })?;
diff --git a/src/kvm_sys.rs b/src/kvm_sys.rs
index 2ce8ba5..d21da47 100644
--- a/src/kvm_sys.rs
+++ b/src/kvm_sys.rs
@@ -1,3 +1,7 @@
+//! Definitions of the system header [`<linux/kvm.h>`][kvm-h].
+//!
+//! [kvm-h]: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/kvm.h
+
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]
diff --git a/src/vcpu.rs b/src/vcpu.rs
index 7d5b8bb..239c663 100644
--- a/src/vcpu.rs
+++ b/src/vcpu.rs
@@ -1,8 +1,17 @@
+//! VCPU system ioctls.
+
use std::fs;
use std::io;
use crate::{ioctl, kvm_sys, KvmRun};
+/// Exit reasons for the [`Vcpu::kvm_run`][crate::vcpu::Vcpu::kvm_run] function.
+///
+/// Details for the different exit reasons can be found in the [`kvm_run`
+/// structure][kvm-run-struct] description.
+///
+/// [kvm-run]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-run
+/// [kvm-run-struct]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#the-kvm-run-structure
pub enum KvmExit<'cpu> {
Halt,
IoIn(u16, &'cpu mut [u8]),
@@ -11,6 +20,13 @@ pub enum KvmExit<'cpu> {
MmioWrite(u64, &'cpu [u8]),
}
+/// Wrapper for VCPU ioctls.
+///
+/// Representation of the file descriptor obtained by the [`KVM_CREATE_VCPU`][kvm-create-vcpu] ioctl.
+/// This wrapper provides access to the `VCPU ioctls` as described in [KVM API][kvm].
+///
+/// [kvm]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#general-description
+/// [kvm-create-vcpu]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-create-vcpu
pub struct Vcpu {
vcpu: fs::File,
kvm_run: KvmRun,
@@ -21,6 +37,10 @@ impl Vcpu {
Vcpu { vcpu, kvm_run }
}
+ /// Get the general purpose registers with the [`KVM_GET_REGS`][kvm-get-regs] ioctl in form of
+ /// [`kvm_regs`](crate::kvm_sys::kvm_regs).
+ ///
+ /// [kvm-get-regs]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-get-regs
pub fn get_regs(&self) -> io::Result<kvm_sys::kvm_regs> {
let mut regs = kvm_sys::kvm_regs::default();
ioctl(
@@ -31,10 +51,18 @@ impl Vcpu {
Ok(regs)
}
+ /// Set the general purpose registers with the [`KVM_SET_REGS`][kvm-set-regs] ioctl in form of
+ /// [`kvm_regs`](crate::kvm_sys::kvm_regs).
+ ///
+ /// [kvm-set-regs]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-set-regs
pub fn set_regs(&self, regs: kvm_sys::kvm_regs) -> io::Result<()> {
ioctl(&self.vcpu, kvm_sys::KVM_SET_REGS, &regs as *const _ as u64).map(|_| ())
}
+ /// Get the special registers with the [`KVM_GET_SREGS`][kvm-get-sregs] ioctl in form of
+ /// [`kvm_sregs`](crate::kvm_sys::kvm_sregs).
+ ///
+ /// [kvm-get-sregs]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-get-sregs
pub fn get_sregs(&self) -> io::Result<kvm_sys::kvm_sregs> {
let mut sregs = kvm_sys::kvm_sregs::default();
ioctl(
@@ -45,6 +73,10 @@ impl Vcpu {
Ok(sregs)
}
+ /// Set the special registers with the [`KVM_SET_SREGS`][kvm-set-sregs] ioctl in form of
+ /// [`kvm_sregs`](crate::kvm_sys::kvm_sregs).
+ ///
+ /// [kvm-set-sregs]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-set-sregs
pub fn set_sregs(&self, sregs: kvm_sys::kvm_sregs) -> io::Result<()> {
ioctl(
&self.vcpu,
@@ -54,6 +86,10 @@ impl Vcpu {
.map(|_| ())
}
+ /// Run the guest VCPU with the [`KVM_RUN`][kvm-run] ioctl until it exits with one of the exit
+ /// reasons described in [`KvmExit`](crate::vcpu::KvmExit).
+ ///
+ /// [kvm-run]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-run
pub fn run(&mut self) -> io::Result<KvmExit<'_>> {
ioctl(&self.vcpu, kvm_sys::KVM_RUN, 0)?;
diff --git a/src/vm.rs b/src/vm.rs
index 6f8a355..95caf3c 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -1,3 +1,5 @@
+//! VM system ioctls.
+
use std::fs;
use std::io;
use std::os::unix::io::FromRawFd;
@@ -5,6 +7,13 @@ use std::os::unix::io::FromRawFd;
use crate::vcpu::Vcpu;
use crate::{ioctl, kvm_sys, KvmRun, PhysAddr, UserMem};
+/// Wrapper for VM ioctls.
+///
+/// Representation of the file descriptor obtained by the [`KVM_CREATE_VM`][kvm-create-vm] ioctl.
+/// This wrapper provides access to the `VM ioctls` as described in [KVM API][kvm].
+///
+/// [kvm]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#general-description
+/// [kvm-create-vm]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-create-vm
pub struct Vm {
vm: fs::File,
vcpu_mmap_size: usize,
@@ -15,12 +24,23 @@ impl Vm {
Vm { vm, vcpu_mmap_size }
}
+ /// Map memory from userspace into the VM as `guest physical` memory starting at address
+ /// `phys_addr`.
+ /// The underlying operation is the [`KVM_SET_USER_MEMORY_REGION`][kmv-set-user-memory-region]
+ /// ioctl.
+ ///
+ /// # Safety
+ ///
+ /// The `mem: &UserMem` argument passed to this function must at least live as long the `Vcpu`
+ /// instance.
+ ///
+ /// [kvm-set-user-memory-region]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-set-user-memory-region
pub unsafe fn set_user_memory_region(
&self,
phys_addr: PhysAddr,
mem: &UserMem,
) -> io::Result<()> {
- // Create guest physical memory mapping for `slot : 0` at guest `phys addr : 0`.
+ // Create guest physical memory mapping for `slot : 0` at guest `phys_addr`.
let mut kvm_mem = kvm_sys::kvm_userspace_memory_region::default();
kvm_mem.userspace_addr = mem.ptr as u64;
kvm_mem.memory_size = mem.len as u64;
@@ -34,6 +54,10 @@ impl Vm {
.map(|_| ())
}
+ /// Create a new virtual cpu with the [`KVM_CREATE_VCPU`][kvm-create-vcpu] ioctl.
+ /// Returns a wrapper [`vcpu::Vcpu`][crate::vcpu::Vcpu] representing the VCPU.
+ ///
+ /// [kvm-create-vcpu]: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-create-vcpu
pub fn create_vpcu(&self, id: u64) -> io::Result<Vcpu> {
let vcpu = ioctl(&self.vm, kvm_sys::KVM_CREATE_VCPU, id)
.map(|fd| unsafe { fs::File::from_raw_fd(fd) })?;
diff --git a/src/x86_64.rs b/src/x86_64.rs
index 978bd84..c16a6ad 100644
--- a/src/x86_64.rs
+++ b/src/x86_64.rs
@@ -1,3 +1,5 @@
+//! `x86_64` flags and bitfields.
+
/* Rflags Register */
/// Carry flag.
@@ -125,6 +127,12 @@ pub const CR4_LA57: u64 = 1 << 5;
/* Extended Feature Enable Register (EFER) */
+/// Extended Feature Enable Register MSR number.
+///
+/// MSR number used with the [`rdmsr`][msr] and [`wrmsr`][msr] instructions to read/write the
+/// `EFER` model specific register.
+///
+/// [msr]: https://johannst.github.io/notes/arch/x86_64.html#model-specific-register-msr
pub const MSR_EFER: u64 = 0xc000_0080;
/// Long Mode Enable.