• Stars
    star
    36
  • Rank 735,472 (Top 15 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created over 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

vm-device

The vm-device crate provides:

  • device traits defining read and write operations on specialized buses
  • device manager (bus-specific traits and a concrete implementation) for operating devices and dispatching I/O
  • abstractions for defining resources and their constraints (e.g. a specific bus address range, IRQ number, etc)

Design

The virtual device model is built around four traits, DevicePio and MutDevicePio for Programmed I/O (PIO), and DeviceMmio and MutDeviceMmio for Memory-mapped I/O (MMIO). The traits define the same methods for handling read and write operations. The difference is that DevicePio and DeviceMmio only require immutable self borrows, whereas MutDevicePio and MutDeviceMmio require mutable borrows.

The device manager abstraction is implemented by the IoManager struct. It defines two buses, one for PIO and one for MMIO. For each bus, with the help of the PioManager and MmioManager traits, the manager provides methods for device registration, as well as for dispatching read and write requests. The manager will determine which device is responsible for handling the I/O request based on the accessed address range, and will route the request to that device.

PioManager and MmioManager traits are useful as interfaces for a couple of reasons. First, to allow for alternative implementations when the provided IoManager is not sufficient. Second, to allow other crates depend on the traits without depending on the actual implementation.

The interaction between a guest kernel, a host kernel and a VMM using IoManager is depicted at the diagram below. A driver in the guest kernel issues an I/O request. That request gets turned by the host kernel’s hypervisor (KVM) into a trigger for the VMM to handle. The trigger is either a vCPU exit or an eventfd notification. The VMM extracts address information and determines the target bus. Then it dispatches a new request to the IoManager, which checks that there’s a virtual device registered on the bus for the requested address, and finally sends the request to that device. vm-device

Usage

A device is usually attached to a particular bus and thus needs to implement a trait of only one type. For example, serial port on x86 is a PIO device, while VirtIO devices use MMIO. It’s also possible for a device to implement both. Once the type of I/O is determined, the next step is to choose between mutable and immutable trait variant. If read or write method needs to mutate the device’s internal state, then the mutable variant must be used.

Before dispatching any I/O requests to the new device, it needs to be registered with an IoManager instance within the specified address range on the bus. Creating a new IoManager is easy by calling IoManager::new() without any configuration. Internally the manager stores devices as trait objects wrapped in Arc’s, therefore if the device implements MutDevicePio or MutDeviceMmio, then it must be wrapped in a Mutex. The crate contains automatic implementation of DevicePio for Mutex<T> where T: MutDevicePio and DeviceMmio for Mutex<T> where T: MutDeviceMmio but only for the Mutex type in the standard library. For any other Mutex type from 3rd party crates the blanket implementation must be done by the user.

From now on the IoManager will be routing I/O requests for the registered address range to the device. The requests are dispatched by the client code, for example when handling VM exits, using IoManager's methods pio_read, pio_write, mmio_read and mmio_write.

Examples

Implementing a simple log PIO device

use std::sync::{Arc, Mutex};
use vm_device::bus::{PioAddress, PioAddressOffset, PioRange};
use vm_device::device_manager::{IoManager, PioManager};
use vm_device::MutDevicePio;

struct LogDevice {}

impl MutDevicePio for LogDevice {
    fn pio_read(&mut self, base: PioAddress, offset: PioAddressOffset, _data: &mut [u8]) {
        println!("mut pio_read: base {:?}, offset {}", base, offset);
    }

    fn pio_write(&mut self, base: PioAddress, offset: PioAddressOffset, data: &[u8]) {
        println!(
            "mut pio_write: base {:?}, offset {}, data {:?}",
            base, offset, data
        );
    }
}

Registering the device with IoManager and performing I/O

fn main() {
    let mut manager = IoManager::new();
    let device = LogDevice {};
    let bus_range = PioRange::new(PioAddress(0), 10).unwrap();
    manager
        .register_pio(bus_range, Arc::new(Mutex::new(device)))
        .unwrap();
    manager.pio_write(PioAddress(0), &vec![b'o', b'k']).unwrap();
}

Testing

The vm-device is tested using unit tests and integration tests. It leverages rust-vmm-ci for continuous testing. All tests are ran in the rustvmm/dev container.

License

This project is licensed under either of:

More Repositories

1

community

rust-vmm community content
459
star
2

vm-virtio

virtio implementation
Rust
370
star
3

vm-memory

Virtual machine's guest memory crate
Rust
310
star
4

kvm-ioctls

Rust
269
star
5

linux-loader

Linux kernel loader
Rust
190
star
6

vmm-reference

A VMM implementation based of rust-vmm components
Rust
147
star
7

vhost

Rust
126
star
8

kvm-bindings

Rust
113
star
9

vmm-sys-util

Helpers and utilities used by multiple rust-vmm components and VMMs
Rust
79
star
10

vhost-device

'vhost-user' device backends workspace
Rust
69
star
11

seccompiler

Provides easy-to-use Linux seccomp-bpf jailing.
Rust
69
star
12

rust-vmm-container

Container with all dependencies required for running rust-vmm crates integration tests.
Shell
65
star
13

event-manager

Rust
45
star
14

mshv

Crates for Microsoft Hypervisor ioctls and bindings
Rust
32
star
15

vm-superio

Emulation for legacy devices
Rust
30
star
16

vm-allocator

Provides allocations and release strategies for resources used during the lifetime of a VM.
Rust
30
star
17

rust-vmm-ci

Python
18
star
18

vhost-user-backend

Deprecated repository, code now lives in: https://github.com/rust-vmm/vhost/
Rust
18
star
19

virtio-bindings

This crate is now part of the vm-virtio workspace: https://github.com/rust-vmm/vm-virtio
Rust
15
star
20

vfio-ioctls

Safe wrappers for VFIO
Rust
15
star
21

vfio

Rust
14
star
22

crate-template

This is the template used by all repositories which represent a crate. The purpose is to speed up the creation of new crates and keep the same standard in rust-vmm.
Rust
12
star
23

vfio-bindings

Rust
11
star
24

vm-fdt

Rust
11
star
25

acpi_tables

Rust
9
star
26

xen-sys

Rust
9
star
27

kvm

Rust
8
star
28

vmm-vcpu

7
star
29

kvm_wrapper

Deprecated. Use https://github.com/rust-vmm/kvm-bindings instead.
Rust
6
star
30

vfio-user

Rust
4
star
31

vm-pci

Rust
2
star
32

io-rate-limiter

Rust
1
star
33

.github

1
star