Struct kvm_ioctls::VmFd

source ·
pub struct VmFd { /* private fields */ }
Expand description

Wrapper over KVM VM ioctls.

Implementations§

source§

impl VmFd

source

pub unsafe fn set_user_memory_region( &self, user_memory_region: kvm_userspace_memory_region ) -> Result<(), Error>

Creates/modifies a guest physical memory slot.

See the documentation for KVM_SET_USER_MEMORY_REGION.

§Arguments
  • user_memory_region - Guest physical memory slot. For details check the kvm_userspace_memory_region structure in the KVM API doc.
§Safety

This function is unsafe because there is no guarantee userspace_addr points to a valid memory region, nor the memory region lives as long as the kernel needs it to.

The caller of this method must make sure that:

  • the raw pointer (userspace_addr) points to valid memory
  • the regions provided to KVM are not overlapping other memory regions.
§Example
extern crate kvm_bindings;

use kvm_bindings::kvm_userspace_memory_region;
use kvm_ioctls::Kvm;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let mem_region = kvm_userspace_memory_region {
    slot: 0,
    guest_phys_addr: 0x10000 as u64,
    memory_size: 0x10000 as u64,
    userspace_addr: 0x0 as u64,
    flags: 0,
};
unsafe {
    vm.set_user_memory_region(mem_region).unwrap();
};
source

pub fn set_tss_address(&self, offset: usize) -> Result<(), Error>

Sets the address of the three-page region in the VM’s address space.

See the documentation for KVM_SET_TSS_ADDR.

§Arguments
  • offset - Physical address of a three-page region in the guest’s physical address space.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
vm.set_tss_address(0xfffb_d000).unwrap();
source

pub fn set_identity_map_address(&self, address: u64) -> Result<(), Error>

Sets the address of the one-page region in the VM’s address space.

See the documentation for KVM_SET_IDENTITY_MAP_ADDR.

§Arguments
  • address - Physical address of a one-page region in the guest’s physical address space.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
vm.set_identity_map_address(0xfffb_c000).unwrap();
source

pub fn create_irq_chip(&self) -> Result<(), Error>

Creates an in-kernel interrupt controller.

See the documentation for KVM_CREATE_IRQCHIP.

§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
vm.create_irq_chip().unwrap();
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
{
    use kvm_bindings::{
        kvm_create_device, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, KVM_CREATE_DEVICE_TEST,
    };
    let mut gic_device = kvm_bindings::kvm_create_device {
        type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2,
        fd: 0,
        flags: KVM_CREATE_DEVICE_TEST,
    };
    if vm.create_device(&mut gic_device).is_ok() {
        vm.create_irq_chip().unwrap();
    }
}
source

pub fn get_irqchip(&self, irqchip: &mut kvm_irqchip) -> Result<(), Error>

X86 specific call to retrieve the state of a kernel interrupt controller.

See the documentation for KVM_GET_IRQCHIP in the KVM API doc.

§Arguments
  • irqchip - kvm_irqchip (input/output) to be read.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

vm.create_irq_chip().unwrap();
let mut irqchip = kvm_irqchip::default();
irqchip.chip_id = KVM_IRQCHIP_PIC_MASTER;
vm.get_irqchip(&mut irqchip).unwrap();
source

pub fn set_irqchip(&self, irqchip: &kvm_irqchip) -> Result<(), Error>

X86 specific call to set the state of a kernel interrupt controller.

See the documentation for KVM_SET_IRQCHIP in the KVM API doc.

§Arguments
  • irqchip - kvm_irqchip (input/output) to be written.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

vm.create_irq_chip().unwrap();
let mut irqchip = kvm_irqchip::default();
irqchip.chip_id = KVM_IRQCHIP_PIC_MASTER;
// Your `irqchip` manipulation here.
vm.set_irqchip(&mut irqchip).unwrap();
source

pub fn create_pit2(&self, pit_config: kvm_pit_config) -> Result<(), Error>

Creates a PIT as per the KVM_CREATE_PIT2 ioctl.

§Arguments
  • pit_config - PIT configuration. For details check the kvm_pit_config structure in the KVM API doc.
§Example
extern crate kvm_bindings;
use kvm_bindings::kvm_pit_config;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let pit_config = kvm_pit_config::default();
vm.create_pit2(pit_config).unwrap();
source

pub fn get_pit2(&self) -> Result<kvm_pit_state2, Error>

X86 specific call to retrieve the state of the in-kernel PIT model.

See the documentation for KVM_GET_PIT2 in the KVM API doc.

§Arguments
  • pitstate - kvm_pit_state2 to be read.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

let pit_config = kvm_pit_config::default();
vm.create_pit2(pit_config).unwrap();
let pitstate = vm.get_pit2().unwrap();
source

pub fn set_pit2(&self, pitstate: &kvm_pit_state2) -> Result<(), Error>

X86 specific call to set the state of the in-kernel PIT model.

See the documentation for KVM_SET_PIT2 in the KVM API doc.

§Arguments
  • pitstate - kvm_pit_state2 to be written.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

let pit_config = kvm_pit_config::default();
vm.create_pit2(pit_config).unwrap();
let mut pitstate = kvm_pit_state2::default();
// Your `pitstate` manipulation here.
vm.set_pit2(&mut pitstate).unwrap();
source

pub fn get_clock(&self) -> Result<kvm_clock_data, Error>

X86 specific call to retrieve the current timestamp of kvmclock.

See the documentation for KVM_GET_CLOCK in the KVM API doc.

§Arguments
  • clock - kvm_clock_data to be read.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let clock = vm.get_clock().unwrap();
source

pub fn set_clock(&self, clock: &kvm_clock_data) -> Result<(), Error>

X86 specific call to set the current timestamp of kvmclock.

See the documentation for KVM_SET_CLOCK in the KVM API doc.

§Arguments
  • clock - kvm_clock_data to be written.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let mut clock = kvm_clock_data::default();
vm.set_clock(&mut clock).unwrap();
source

pub fn signal_msi(&self, msi: kvm_msi) -> Result<c_int, Error>

Directly injects a MSI message as per the KVM_SIGNAL_MSI ioctl.

See the documentation for KVM_SIGNAL_MSI.

This ioctl returns > 0 when the MSI is successfully delivered and 0 when the guest blocked the MSI.

§Arguments
  • kvm_msi - MSI message configuration. For details check the kvm_msi structure in the KVM API doc.
§Example

In this example, the important function signal_msi() calling into the actual ioctl is commented out. The reason is that MSI vectors are not chosen from the HW side (VMM). The guest OS (or anything that runs inside the VM) is supposed to allocate the MSI vectors, and usually communicate back through PCI configuration space. Sending a random MSI vector through this signal_msi() function will always result in a failure, which is why it needs to be commented out.

extern crate kvm_bindings;
use kvm_bindings::kvm_msi;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let msi = kvm_msi::default();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
vm.create_irq_chip().unwrap();
//vm.signal_msi(msi).unwrap();
source

pub fn set_gsi_routing( &self, irq_routing: &kvm_irq_routing ) -> Result<(), Error>

Sets the GSI routing table entries, overwriting any previously set entries, as per the KVM_SET_GSI_ROUTING ioctl.

See the documentation for KVM_SET_GSI_ROUTING.

Returns an io::Error when the table could not be updated.

§Arguments
  • kvm_irq_routing - IRQ routing configuration. Describe all routes associated with GSI entries. For details check the kvm_irq_routing and kvm_irq_routing_entry structures in the KVM API doc.
§Example
extern crate kvm_bindings;
use kvm_bindings::kvm_irq_routing;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
vm.create_irq_chip().unwrap();

let irq_routing = kvm_irq_routing::default();
vm.set_gsi_routing(&irq_routing).unwrap();
source

pub fn register_ioevent<T: Into<u64>>( &self, fd: &EventFd, addr: &IoEventAddress, datamatch: T ) -> Result<(), Error>

Registers an event to be signaled whenever a certain address is written to.

See the documentation for KVM_IOEVENTFD.

§Arguments
  • fd - EventFd which will be signaled. When signaling, the usual vmexit to userspace is prevented.
  • addr - Address being written to.
  • datamatch - Limits signaling fd to only the cases where the value being written is equal to this parameter. The size of datamatch is important and it must match the expected size of the guest’s write.
§Example
extern crate libc;
extern crate vmm_sys_util;
use libc::{eventfd, EFD_NONBLOCK};
use vmm_sys_util::eventfd::EventFd;
let kvm = Kvm::new().unwrap();
let vm_fd = kvm.create_vm().unwrap();
let evtfd = EventFd::new(EFD_NONBLOCK).unwrap();
vm_fd
    .register_ioevent(&evtfd, &IoEventAddress::Pio(0xf4), NoDatamatch)
    .unwrap();
vm_fd
    .register_ioevent(&evtfd, &IoEventAddress::Mmio(0x1000), NoDatamatch)
    .unwrap();
source

pub fn unregister_ioevent<T: Into<u64>>( &self, fd: &EventFd, addr: &IoEventAddress, datamatch: T ) -> Result<(), Error>

Unregisters an event from a certain address it has been previously registered to.

See the documentation for KVM_IOEVENTFD.

§Arguments
  • fd - FD which will be unregistered.
  • addr - Address being written to.
§Safety

This function is unsafe because it relies on RawFd.

§Example
extern crate libc;
extern crate vmm_sys_util;
use libc::EFD_NONBLOCK;
use vmm_sys_util::eventfd::EventFd;

let kvm = Kvm::new().unwrap();
let vm_fd = kvm.create_vm().unwrap();
let evtfd = EventFd::new(EFD_NONBLOCK).unwrap();
let pio_addr = IoEventAddress::Pio(0xf4);
let mmio_addr = IoEventAddress::Mmio(0x1000);
vm_fd
    .register_ioevent(&evtfd, &pio_addr, NoDatamatch)
    .unwrap();
vm_fd
    .register_ioevent(&evtfd, &mmio_addr, 0x1234u32)
    .unwrap();
vm_fd
    .unregister_ioevent(&evtfd, &pio_addr, NoDatamatch)
    .unwrap();
vm_fd
    .unregister_ioevent(&evtfd, &mmio_addr, 0x1234u32)
    .unwrap();
source

pub fn get_dirty_log( &self, slot: u32, memory_size: usize ) -> Result<Vec<u64>, Error>

Gets the bitmap of pages dirtied since the last call of this function.

Leverages the dirty page logging feature in KVM. As a side-effect, this also resets the bitmap inside the kernel. For the dirty log to be available, you have to set the flag KVM_MEM_LOG_DIRTY_PAGES when creating guest memory regions.

Check the documentation for KVM_GET_DIRTY_LOG.

§Arguments
  • slot - Guest memory slot identifier.
  • memory_size - Size of the memory region.
§Example
// This example is based on https://lwn.net/Articles/658511/.
let mem_size = 0x4000;
let guest_addr: u64 = 0x1000;
let load_addr: *mut u8 = unsafe {
    libc::mmap(
        null_mut(),
        mem_size,
        libc::PROT_READ | libc::PROT_WRITE,
        libc::MAP_ANONYMOUS | libc::MAP_SHARED | libc::MAP_NORESERVE,
        -1,
        0,
    ) as *mut u8
};

// Initialize a guest memory region using the flag `KVM_MEM_LOG_DIRTY_PAGES`.
let mem_region = kvm_userspace_memory_region {
    slot: 0,
    guest_phys_addr: guest_addr,
    memory_size: mem_size as u64,
    userspace_addr: load_addr as u64,
    flags: KVM_MEM_LOG_DIRTY_PAGES,
};
unsafe { vm.set_user_memory_region(mem_region).unwrap() };

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
// ASM code that just forces a MMIO Write.
let asm_code = [0xc6, 0x06, 0x00, 0x80, 0x00];
#[cfg(target_arch = "aarch64")]
let asm_code = [
    0x01, 0x00, 0x00, 0x10, /* adr x1, <this address> */
    0x22, 0x10, 0x00, 0xb9, /* str w2, [x1, #16]; write to this page */
    0x02, 0x00, 0x00, 0xb9, /* str w2, [x0]; force MMIO exit */
    0x00, 0x00, 0x00,
    0x14, /* b <this address>; shouldn't get here, but if so loop forever */
];

// Write the code in the guest memory. This will generate a dirty page.
unsafe {
    let mut slice = slice::from_raw_parts_mut(load_addr, mem_size);
    slice.write(&asm_code).unwrap();
}

let mut vcpu_fd = vm.create_vcpu(0).unwrap();

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
    // x86_64 specific registry setup.
    let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
    vcpu_sregs.cs.base = 0;
    vcpu_sregs.cs.selector = 0;
    vcpu_fd.set_sregs(&vcpu_sregs).unwrap();

    let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
    // Set the Instruction Pointer to the guest address where we loaded the code.
    vcpu_regs.rip = guest_addr;
    vcpu_regs.rax = 2;
    vcpu_regs.rbx = 3;
    vcpu_regs.rflags = 2;
    vcpu_fd.set_regs(&vcpu_regs).unwrap();
}

#[cfg(target_arch = "aarch64")]
{
    // aarch64 specific registry setup.
    let mut kvi = kvm_bindings::kvm_vcpu_init::default();
    vm.get_preferred_target(&mut kvi).unwrap();
    vcpu_fd.vcpu_init(&kvi).unwrap();

    let core_reg_base: u64 = 0x6030_0000_0010_0000;
    let mmio_addr: u64 = guest_addr + mem_size as u64;
    vcpu_fd.set_one_reg(core_reg_base + 2 * 32, &guest_addr.to_le_bytes()); // set PC
    vcpu_fd.set_one_reg(core_reg_base + 2 * 0, &mmio_addr.to_le_bytes()); // set X0
}

loop {
    match vcpu_fd.run().expect("run failed") {
        VcpuExit::MmioWrite(addr, data) => {
            // On x86_64, the code snippet dirties 1 page when loading the code in memory
            // while on aarch64 the dirty bit comes from writing to guest_addr (current PC).
            let dirty_pages_bitmap = vm.get_dirty_log(0, mem_size).unwrap();
            let dirty_pages = dirty_pages_bitmap
                .into_iter()
                .map(|page| page.count_ones())
                .fold(0, |dirty_page_count, i| dirty_page_count + i);
            assert_eq!(dirty_pages, 1);
            break;
        }
        exit_reason => panic!("unexpected exit reason: {:?}", exit_reason),
    }
}
source

pub fn register_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<(), Error>

Registers an event that will, when signaled, trigger the gsi IRQ.

§Arguments
  • fd - EventFd to be signaled.
  • gsi - IRQ to be triggered.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let evtfd = EventFd::new(EFD_NONBLOCK).unwrap();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
    vm.create_irq_chip().unwrap();
    vm.register_irqfd(&evtfd, 0).unwrap();
}
source

pub fn register_irqfd_with_resample( &self, fd: &EventFd, resamplefd: &EventFd, gsi: u32 ) -> Result<(), Error>

Registers an event that will, when signaled, assert the gsi IRQ. If the irqchip is resampled by the guest, the IRQ is de-asserted, and resamplefd is notified.

§Arguments
  • fd - EventFd to be signaled.
  • resamplefd - EventFdto be notified on resample.
  • gsi - IRQ to be triggered.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let evtfd = EventFd::new(EFD_NONBLOCK).unwrap();
let resamplefd = EventFd::new(EFD_NONBLOCK).unwrap();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
    vm.create_irq_chip().unwrap();
    vm.register_irqfd_with_resample(&evtfd, &resamplefd, 0)
        .unwrap();
}
source

pub fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<(), Error>

Unregisters an event that will, when signaled, trigger the gsi IRQ.

§Arguments
  • fd - EventFd to be signaled.
  • gsi - IRQ to be triggered.
§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let evtfd = EventFd::new(EFD_NONBLOCK).unwrap();
let resamplefd = EventFd::new(EFD_NONBLOCK).unwrap();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
    vm.create_irq_chip().unwrap();
    vm.register_irqfd(&evtfd, 0).unwrap();
    vm.unregister_irqfd(&evtfd, 0).unwrap();
    vm.register_irqfd_with_resample(&evtfd, &resamplefd, 0)
        .unwrap();
    vm.unregister_irqfd(&evtfd, 0).unwrap();
}
source

pub fn set_irq_line(&self, irq: u32, active: bool) -> Result<(), Error>

Sets the level on the given irq to 1 if active is true, and 0 otherwise.

§Arguments
  • irq - IRQ to be set.
  • active - Level of the IRQ input.
§Errors

Returns an io::Error when the irq field is invalid

§Examples
fn arch_setup(vm_fd: &VmFd) {
    // Arch-specific setup:
    // For x86 architectures, it simply means calling vm.create_irq_chip().unwrap().
    // For Arm architectures, the IRQ controllers need to be setup first.
    // Details please refer to the kernel documentation.
    // https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt
}

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
arch_setup(&vm);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
    vm.set_irq_line(4, true);
    // ...
}
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
{
    vm.set_irq_line(0x01_00_0020, true);
    // ....
}
source

pub fn create_vcpu(&self, id: u64) -> Result<VcpuFd, Error>

Creates a new KVM vCPU file descriptor and maps the memory corresponding its kvm_run structure.

See the documentation for KVM_CREATE_VCPU.

§Arguments
  • id - The vCPU ID.
§Errors

Returns an io::Error when the VM fd is invalid or the vCPU memory cannot be mapped correctly.

§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
// Create one vCPU with the ID=0.
let vcpu = vm.create_vcpu(0);
source

pub unsafe fn create_vcpu_from_rawfd(&self, fd: RawFd) -> Result<VcpuFd, Error>

Creates a VcpuFd object from a vcpu RawFd.

§Arguments
  • fd - the RawFd used for creating the VcpuFd object.
§Safety

This function is unsafe as the primitives currently returned have the contract that they are the sole owner of the file descriptor they are wrapping. Usage of this function could accidentally allow violating this contract which can cause memory unsafety in code that relies on it being true.

The caller of this method must make sure the fd is valid and nothing else uses it.

§Example
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
// Create one vCPU with the ID=0.
let vcpu = vm.create_vcpu(0).unwrap();
let rawfd = unsafe { libc::dup(vcpu.as_raw_fd()) };
assert!(rawfd >= 0);
let vcpu = unsafe { vm.create_vcpu_from_rawfd(rawfd).unwrap() };
source

pub fn create_device( &self, device: &mut kvm_create_device ) -> Result<DeviceFd, Error>

Creates an emulated device in the kernel.

See the documentation for KVM_CREATE_DEVICE.

§Arguments
  • device: device configuration. For details check the kvm_create_device structure in the KVM API doc.
§Example
use kvm_bindings::{
    kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3,
    kvm_device_type_KVM_DEV_TYPE_VFIO, KVM_CREATE_DEVICE_TEST,
};
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

// Creating a device with the KVM_CREATE_DEVICE_TEST flag to check
// whether the device type is supported. This will not create the device.
// To create the device the flag needs to be removed.
let mut device = kvm_bindings::kvm_create_device {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    type_: kvm_device_type_KVM_DEV_TYPE_VFIO,
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3,
    fd: 0,
    flags: KVM_CREATE_DEVICE_TEST,
};
// On ARM, creating VGICv3 may fail due to hardware dependency.
// Retry to create VGICv2 in that case.
let device_fd = vm.create_device(&mut device).unwrap_or_else(|_| {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    panic!("Cannot create VFIO device.");
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    {
        device.type_ = kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2;
        vm.create_device(&mut device)
            .expect("Cannot create vGIC device")
    }
});
source

pub fn enable_cap(&self, cap: &kvm_enable_cap) -> Result<(), Error>

Enable the specified capability as per the KVM_ENABLE_CAP ioctl.

See the documentation for KVM_ENABLE_CAP.

Returns an io::Error when the capability could not be enabled.

§Arguments
  • kvm_enable_cap - KVM capability structure. For details check the kvm_enable_cap structure in the KVM API doc.
§Example
extern crate kvm_bindings;

use kvm_bindings::{kvm_enable_cap, KVM_CAP_SPLIT_IRQCHIP};

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let mut cap: kvm_enable_cap = Default::default();
// This example cannot enable an arm/aarch64 capability since there
// is no capability available for these architectures.
if cfg!(target_arch = "x86") || cfg!(target_arch = "x86_64") {
    cap.cap = KVM_CAP_SPLIT_IRQCHIP;
    // As per the KVM documentation, KVM_CAP_SPLIT_IRQCHIP only emulates
    // the local APIC in kernel, expecting that a userspace IOAPIC will
    // be implemented by the VMM.
    // Along with this capability, the user needs to specify the number
    // of pins reserved for the userspace IOAPIC. This number needs to be
    // provided through the first argument of the capability structure, as
    // specified in KVM documentation:
    //     args[0] - number of routes reserved for userspace IOAPICs
    //
    // Because an IOAPIC supports 24 pins, that's the reason why this test
    // picked this number as reference.
    cap.args[0] = 24;
    vm.enable_cap(&cap).unwrap();
}
source

pub fn run_size(&self) -> usize

Get the kvm_run size.

source

pub fn check_extension(&self, c: Cap) -> bool

Checks if a particular Cap is available.

Returns true if the capability is supported and false otherwise. See the documentation for KVM_CHECK_EXTENSION.

§Arguments
  • c - VM capability to check.
§Example
use kvm_ioctls::Cap;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
// Check if `KVM_CAP_MP_STATE` is supported.
assert!(vm.check_extension(Cap::MpState));
source

pub unsafe fn encrypt_op<T>(&self, op: *mut T) -> Result<(), Error>

Issues platform-specific memory encryption commands to manage encrypted VMs if the platform supports creating those encrypted VMs.

Currently, this ioctl is used for issuing Secure Encrypted Virtualization (SEV) commands on AMD Processors.

See the documentation for KVM_MEMORY_ENCRYPT_OP in the KVM API doc.

For SEV-specific functionality, prefer safe wrapper:

§Safety

This function is unsafe because there is no guarantee T is valid in this context, how much data kernel will read from memory and where it will write data on error.

§Arguments
  • op - an opaque platform specific structure.
§Example
use kvm_bindings::bindings::kvm_sev_cmd;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

// Initialize the SEV platform context.
let mut init: kvm_sev_cmd = Default::default();
unsafe { vm.encrypt_op(&mut init).unwrap() };
source

pub fn encrypt_op_sev(&self, op: &mut kvm_sev_cmd) -> Result<(), Error>

Issue common lifecycle events of SEV guests, such as launching, running, snapshotting, migrating and decommissioning via KVM_MEMORY_ENCRYPT_OP ioctl.

Kernel documentation states that this ioctl can be used for testing whether SEV is enabled by sending NULL. To do that, pass std::ptr::null_mut to encrypt_op.

See the documentation for Secure Encrypted Virtualization (SEV).

§Arguments
§Example
use kvm_bindings::bindings::kvm_sev_cmd;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

// Check whether SEV is enabled, optional.
assert!(unsafe { vm.encrypt_op(null_mut() as *mut c_void) }.is_ok());

// Initialize the SEV platform context.
let mut init: kvm_sev_cmd = Default::default();
vm.encrypt_op_sev(&mut init).unwrap();
source

pub fn register_enc_memory_region( &self, memory_region: &kvm_enc_region ) -> Result<(), Error>

Register a guest memory region which may contain encrypted data.

It is used in the SEV-enabled guest.

See the documentation for KVM_MEMORY_ENCRYPT_REG_REGION in the KVM API doc.

§Arguments
  • memory_region - Guest physical memory region.
§Example
use kvm_bindings::bindings::{kvm_enc_region, kvm_sev_cmd, kvm_sev_launch_start, sev_cmd_id_KVM_SEV_LAUNCH_START};
use libc;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let sev = OpenOptions::new()
    .read(true)
    .write(true)
    .open("/dev/sev")
    .unwrap();

// Initialize the SEV platform context.
let mut init: kvm_sev_cmd = Default::default();
assert!(vm.encrypt_op_sev(&mut init).is_ok());

// Create the memory encryption context.
let start_data: kvm_sev_launch_start = Default::default();
let mut start = kvm_sev_cmd {
    id: sev_cmd_id_KVM_SEV_LAUNCH_START,
    data: &start_data as *const kvm_sev_launch_start as _,
    sev_fd: sev.as_raw_fd() as _,
    ..Default::default()
};
assert!(vm.encrypt_op_sev(&mut start).is_ok());

let addr = unsafe {
    libc::mmap(
        null_mut(),
        4096,
        libc::PROT_READ | libc::PROT_WRITE,
        libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
        -1,
        0,
    )
};
assert_ne!(addr, libc::MAP_FAILED);

let memory_region = kvm_enc_region {
    addr: addr as _,
    size: 4096,
};
vm.register_enc_memory_region(&memory_region).unwrap();
source

pub fn unregister_enc_memory_region( &self, memory_region: &kvm_enc_region ) -> Result<(), Error>

Unregister a guest memory region registered with register_enc_memory_region.

It is used in the SEV-enabled guest.

See the documentation for KVM_MEMORY_ENCRYPT_UNREG_REGION in the KVM API doc.

§Arguments
  • memory_region - Guest physical memory region.
§Example
use kvm_bindings::bindings::{kvm_enc_region, kvm_sev_cmd, kvm_sev_launch_start, sev_cmd_id_KVM_SEV_LAUNCH_START};
use libc;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let sev = OpenOptions::new()
    .read(true)
    .write(true)
    .open("/dev/sev")
    .unwrap();

// Initialize the SEV platform context.
let mut init: kvm_sev_cmd = Default::default();
assert!(vm.encrypt_op_sev(&mut init).is_ok());

// Create the memory encryption context.
let start_data: kvm_sev_launch_start = Default::default();
let mut start = kvm_sev_cmd {
    id: sev_cmd_id_KVM_SEV_LAUNCH_START,
    data: &start_data as *const kvm_sev_launch_start as _,
    sev_fd: sev.as_raw_fd() as _,
    ..Default::default()
};
assert!(vm.encrypt_op_sev(&mut start).is_ok());

let addr = unsafe {
    libc::mmap(
        null_mut(),
        4096,
        libc::PROT_READ | libc::PROT_WRITE,
        libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
        -1,
        0,
    )
};
assert_ne!(addr, libc::MAP_FAILED);

let memory_region = kvm_enc_region {
    addr: addr as _,
    size: 4096,
};
vm.register_enc_memory_region(&memory_region).unwrap();
vm.unregister_enc_memory_region(&memory_region).unwrap();
source

pub fn register_coalesced_mmio( &self, addr: IoEventAddress, size: u32 ) -> Result<(), Error>

Registers an address for coalesced MMIO. Write accesses to the address will not cause a corresponding VcpuExit, but instead will be appended to the MMIO ring buffer. The VcpuFd can read entries in the ring buffer via VcpuFd::coalesced_mmio_read(). If entries are not read the buffer will eventually be full, preventing further elements from being appended by the kernel.

Needs KVM_CAP_COALESCED_MMIO (Cap::CoalescedMmio) and/or KVM_CAP_COALESCED_PIO (Cap::CoalescedMmio).

See the documentation for KVM_REGISTER_COALESCED_MMIO.

§Arguments
  • addr - Address being written to.
  • size - The size of the write for the mechanism to trigger.
source

pub fn unregister_coalesced_mmio( &self, addr: IoEventAddress, size: u32 ) -> Result<(), Error>

Unregister an address that was previously registered via register_coalesced_mmio().

See the documentation for KVM_UNREGISTER_COALESCED_MMIO.

Trait Implementations§

source§

impl AsRawFd for VmFd

source§

fn as_raw_fd(&self) -> RawFd

Extracts the raw file descriptor. Read more
source§

impl Debug for VmFd

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for VmFd

§

impl RefUnwindSafe for VmFd

§

impl Send for VmFd

§

impl Sync for VmFd

§

impl Unpin for VmFd

§

impl UnwindSafe for VmFd

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.