Skip to content

Commit

Permalink
Merge branch 'main' into lizebin/move-iter-out
Browse files Browse the repository at this point in the history
  • Loading branch information
cutelizebin authored Sep 7, 2023
2 parents dc7148c + c0a5c39 commit c7b1df0
Show file tree
Hide file tree
Showing 29 changed files with 5,566 additions and 184 deletions.
292 changes: 139 additions & 153 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[workspace]
resolver = "2"

members = [
"crates/gpio",
"crates/i2c",
"crates/rng",
"crates/scsi",
"crates/scmi",
"crates/vsock",
]
2 changes: 1 addition & 1 deletion coverage_config_x86_64.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"coverage_score": 68.2,
"coverage_score": 71.0,
"exclude_path": "",
"crate_features": ""
}
2 changes: 1 addition & 1 deletion crates/i2c/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl SmbusMsg {
///
/// These smbus related functions try to reverse what Linux does, only
/// support basic modes (up to word transfer).
fn new(reqs: &mut [I2cReq]) -> Result<SmbusMsg> {
fn new(reqs: &[I2cReq]) -> Result<SmbusMsg> {
let mut data = I2cSmbusData {
block: [0; I2C_SMBUS_BLOCK_MAX + 2],
};
Expand Down
15 changes: 15 additions & 0 deletions crates/scmi/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog
## [Unreleased]

### Added

### Changed

### Fixed

### Deprecated

## [0.1.0]

First release

27 changes: 27 additions & 0 deletions crates/scmi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "vhost-device-scmi"
version = "0.1.0"
authors = ["Milan Zamazal <[email protected]>"]
description = "vhost-user SCMI backend device"
repository = "https://github.com/rust-vmm/vhost-device"
readme = "README.md"
keywords = ["scmi", "vhost", "virt", "backend"]
license = "Apache-2.0 OR BSD-3-Clause"
edition = "2021"

[dependencies]
clap = { version = "4.3", features = ["derive"] }
env_logger = "0.10"
itertools = "0.10"
log = "0.4"
thiserror = "1.0"
vhost = { version = "0.8", features = ["vhost-user-slave"] }
vhost-user-backend = "0.10"
virtio-bindings = "0.2"
virtio-queue = "0.9"
vm-memory = "0.12"
vmm-sys-util = "0.11"

[dev-dependencies]
assert_matches = "1.5"
virtio-queue = { version = "0.9", features = ["test-utils"] }
1 change: 1 addition & 0 deletions crates/scmi/LICENSE-APACHE
1 change: 1 addition & 0 deletions crates/scmi/LICENSE-BSD-3-Clause
104 changes: 104 additions & 0 deletions crates/scmi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# vhost-device-scmi

This program is a vhost-user backend for a VirtIO SCMI device.
It provides SCMI access to various entities on the host; not
necessarily only those providing an SCMI interface themselves.

It is tested with QEMU's `-device vhost-user-scmi-pci` but should work
with any virtual machine monitor (VMM) that supports vhost-user. See
the Examples section below.

## Synopsis

**vhost-device-scmi** [*OPTIONS*]

## Options

.. program:: vhost-device-scmi

.. option:: -h, --help

Print help.

.. option:: -s, --socket-path=PATH

Location of the vhost-user Unix domain sockets.

.. option:: -d, --device=SPEC

SCMI device specification in the format `ID,PROPERTY=VALUE,...`.
For example: `-d iio,path=/sys/bus/iio/devices/iio:device0,channel=in_accel`.
Can be used multiple times for multiple exposed devices.
If no device is specified then no device will be provided to the
guest OS but VirtIO SCMI will be still available there.
Use `--help-devices` to list help on all the available devices.

You can set `RUST_LOG` environment variable to `debug` to get maximum
messages on the standard error output.

## Examples

The daemon should be started first:

::

host# vhost-device-scmi --socket-path=scmi.sock --device fake,name=foo

The QEMU invocation needs to create a chardev socket the device can
use to communicate as well as share the guests memory over a memfd:

::

host# qemu-system \
-chardev socket,path=scmi.sock,id=scmi \
-device vhost-user-scmi-pci,chardev=vscmi,id=scmi \
-machine YOUR-MACHINE-OPTIONS,memory-backend=mem \
-m 4096 \
-object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on \
...

## Supported SCMI protocols

The currently supported SCMI protocols are:

- base
- sensor management

Basically only the mandatory and necessary parts of the protocols are
implemented.

See source code (`scmi` crate) documentation for details and how to
add more protocols, host device bindings or other functionality.

## Testing

SCMI is supported only on Arm in Linux. This restriction doesn't
apply to the host, which can be any architecture as long as the guest
is Arm.

The easiest way to test it on the guest side is using the Linux SCMI
Industrial I/O driver there. If an 3-axes accelerometer or gyroscope
VirtIO SCMI device is present and the guest kernel is compiled with
`CONFIG_IIO_SCMI` enabled then the device should be available in
`/sys/bus/iio/devices/`. The vhost-device-scmi fake device is
suitable for this.

Of course, other means of accessing SCMI devices can be used too. The
following Linux kernel command line can be useful to obtain SCMI trace
information, in addition to SCMI related messages in dmesg:
`trace_event=scmi:* ftrace=function ftrace_filter=scmi*`.

### Kernel support for testing

`kernel` subdirectory contains
[instructions](kernel/iio-dummy/README.md) how to create emulated
industrial I/O devices for testing.

## License

This project is licensed under either of

- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0
- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause)

unless specified in particular files otherwise.
7 changes: 7 additions & 0 deletions crates/scmi/kernel/iio-dummy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*.cmd
*.ko
*.mod
*.mod.[co]
*.o
Module.symvers
modules.order
19 changes: 19 additions & 0 deletions crates/scmi/kernel/iio-dummy/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the IIO Dummy Driver
#
# Modified by Milan Zamazal <[email protected]> in 2023 for out of
# tree compilation.
#

obj-m += iio_modified_dummy.o

on_nixos = $(wildcard /etc/NIXOS)
ifeq ($(on_nixos), /etc/NIXOS)
nix_prefix = $(shell nix-build -E '(import <nixpkgs> {}).linux.dev' --no-out-link)
endif

all:
make -C $(nix_prefix)/lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C $(nix_prefix)/lib/modules/$(shell uname -r)/build M=$(PWD) clean
185 changes: 185 additions & 0 deletions crates/scmi/kernel/iio-dummy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Using emulated industrial I/O devices

This is a modified version of the Linux [industrial I/O dummy
driver](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/dummy).
Both the original driver and this modification can provide emulated
industrial I/O devices for testing vhost-device-scmi.

## Modifications in this module

If the stock industrial I/O dummy driver is enough for you, use it
(but you may still want to read the instructions below).

Otherwise, this alternative is provided with the following changes:

- Simplified Makefile for out of tree compilation.
- The accelerometer has three axes instead of just one.
- The Y axis of the accelerometer has offset and scale.

Of course, you can modified it further for your liking if needed.

## How to create emulated industrial I/O devices

Make sure your kernel supports software industrial I/O devices and
industrial I/O with configfs. You can check this by running `modprobe
industrialio_sw_device && modprobe industrialio_configfs`. If any of
the modules is not present, follow the [instructions for recompiling
kernel](#recompiling-kernel-with-industrial-io) below.

Make sure you have the right kernel version. Since Linux 5.19, the
dummy industrial I/O driver is broken. This will be probably fixed in
Linux 6.6.

If you have a broken kernel version, apply the
[fix](./iio-dummy-fix.patch) and compile and install the modified
kernel.

If you want to use the modified module from here, compile it. In
order to do this, you must have kernel development environment
installed, for example:

- Fedora or derivatives: `dnf install kernel-devel kernel-modules make`
- Debian or derivatives: `apt install linux-headers-$(uname -r) make`
- NixOS: `nix-shell '<nixpkgs>' -A linux.dev`

Then you can compile the module, simply running `make` should work on
most distributions.

Insert a dummy industrial I/O kernel module. Either the stock one:

```
# modprobe iio-dummy
```

or the modified one from here:

```
# modprobe industrialio
# modprobe industrialio_configfs
# modprobe industrialio_sw_device
# insmod ./iio-dummy-modified.ko
```

Find out where configfs is mounted: `mount | grep configfs`. It's
typically `/sys/kernel/config`. If configfs is not mounted, mount it
somewhere: `mount -t configfs none MOUNTPOINT`.

Now you can create emulated industrial I/O devices with the stock driver:

```
# mkdir /sys/kernel/config/iio/devices/dummy/my-device
```

And/or with the modified driver from here:

```
# mkdir /sys/kernel/config/iio/devices/dummy-modified/my-device
```

If everything is OK then you can find the device in
`/sys/bus/iio/devices/`.

## Recompiling kernel with industrial I/O

Making a custom kernel is different on each GNU/Linux distribution.
The corresponding documentation can be found for example here:

- Fedora: [https://fedoraproject.org/wiki/Building_a_custom_kernel](https://fedoraproject.org/wiki/Building_a_custom_kernel)
- CentOS Stream: [https://wiki.centos.org/HowTos/BuildingKernelModules](https://wiki.centos.org/HowTos/BuildingKernelModules)
(looks more useful for Fedora builds than CentOS)
- Debian: [https://kernel-team.pages.debian.net/kernel-handbook/ch-common-tasks.html#s-common-official](https://kernel-team.pages.debian.net/kernel-handbook/ch-common-tasks.html#s-common-official)
- NixOS: [https://nixos.wiki/wiki/Linux_kernel](https://nixos.wiki/wiki/Linux_kernel)

Here are instructions for Fedora, similar steps can be used for other
distributions, with distribution specifics as described in the links
above. This is not necessarily the most official or the best way to
do it but it's a way that *actually works* for me.

Note on CentOS Stream 9: The kernel there doesn't contain the needed
modules. Recompiling the kernel on CentOS Stream may be challenging
due to missing build dependencies. If it doesn't work for you, you
can try to use Fedora kernel and modules on CentOS Stream, including
the dummy module compiled on Fedora.

### Install kernel sources

```
# dnf install 'dnf-command(download)'
$ dnf download --source kernel
$ rpm -i kernel-*.src.rpm
# dnf builddep ~/rpmbuild/SPECS/kernel.spec
```

### Change kernel configuration

Not needed for current Fedora but may be needed for e.g. CentOS Stream.

```
# dnf install kernel-devel kernel-modules make rpm-build python3-devel ncurses-devel
$ rpmbuild -bp ~/rpmbuild/SPECS/kernel.spec
$ cd ~/rpmbuild/BUILD/kernel-*/linux-*/
$ cp configs/kernel-VERSION-YOURARCH.config .config
$ make nconfig
```

Configuration options that must be enabled:

- Device Drivers -> Industrial I/O Support -> Enable IIO configuration via configfs
- Device Drivers -> Industrial I/O Support -> Enable software IIO device support

Optionally (you can use the alternative driver from here instead):

- Device Drivers -> Industrial I/O Support -> IIO dummy drive -> An example driver with no hardware requirements

Then copy `.config` back to its original file and don't forget to add
the original architecture specification line there.

### Apply the kernel fix

If the kernel fix from here is needed, copy it to the sources:

```
cp .../iio-dummy-fix.patch ~/rpmbuild/SOURCES/
```

Edit `~/rpmbuild/SPECS/kernel.spec`:

- Uncomment: `%define buildid .local`.

- Add the patch file before: `Patch999999: linux-kernel-test.patch`.

- Add the patch file before: `ApplyOptionalPatch linux-kernel-test.patch`.

### Build the kernel

You can use different options, if you don't need anything extra then
the following builds the most important rpm's:

```
$ rpmbuild -bb --with baseonly --without debug --without debuginfo ~/rpmbuild/SPECS/kernel.spec
```

## Adding industrial I/O dummy module to your kernel

If all you need is to add a missing stock I/O dummy module, you can
try to compile just the module. Switch to kernel sources and run:

```
$ make oldconfig
$ make prepare
$ make modules_prepare
$ make M=drivers/iio/dummy
```

And insert the module:

```
# modprobe industrialio
# modprobe industrialio_configfs
# modprobe industrialio_sw_device
# insmod ./drivers/iio/dummy/iio-dummy.ko
```

If this fails, inspect `dmesg` output and try to figure out what's
wrong. If this fails too, rebuild the whole kernel with the given
module enabled.
Loading

0 comments on commit c7b1df0

Please sign in to comment.