Compare commits

..

67 Commits
v44.0 ... v45.0

Author SHA1 Message Date
Bo Chen
3d88996e5b build: Release v45.0
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-03-29 16:44:09 +00:00
Ruoqing He
3899cd0e30 docs: Add guide for direct boot VM on riscv64
Add `riscv.md` to guide developers/users on preparing guest kernel,
image, and direct boot VM on riscv64 platforms; document support status
and known limitations.

Co-authored-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-29 03:58:12 +00:00
Jinrong Liang
9d93df4c8f vm-migration: Optimize downtime by moving stop_dirty_log()
The larger the VM memory, the greater the memory pressure, and the
greater the stop_dirty_log() overhead. Moving stop_dirty_log() outside
the downtime period can reduce downtime.

Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
2025-03-27 21:08:33 +00:00
Jinrong Liang
4c27572b87 vm-migration: Avoid stop_dirty_log() during local migration
Starting and stopping logging dirty pages only occurs during cross-host
migrations.

Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
2025-03-27 21:08:33 +00:00
Ruoqing He
19fea1ad88 hypervisor: Simplify riscv64 set_regs implementation
Use `riscv64_set_one_reg_from_vcpu!` macro to simplify `set_regs` for
riscv64.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-27 00:27:05 +00:00
Ruoqing He
9a96ea44be hypervisor: Introduce riscv64_set_one_reg_to_vcpu macro
`riscv64_set_one_reg_to_vcpu` macro is used to set value of specific
RISC-V `$reg_name` stored in `state` to KVM Vcpu.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-27 00:27:05 +00:00
Ruoqing He
e11b9d6449 hypervisor: Simplify riscv64 get_regs implementation
Use `riscv64_get_one_reg_from_vcpu!` macro to simplify `get_regs` for
riscv64.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-27 00:27:05 +00:00
Ruoqing He
ce5fe7f89d hypervisor: Introduce riscv64_get_one_reg_from_vcpu macro
`riscv64_get_one_reg_from_vcpu` macro is used to extract RISC-V register
data from KVM Vcpu according to `$reg_name` provided to `state`.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-27 00:27:05 +00:00
Ruoqing He
0dd0364bf8 build: Centralize igvm crates to workspace
`igvm` crates are referenced by multiple components, centralize them to
workspace to better manage those crates.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-24 18:01:03 +00:00
Jinank Jain
3081d01fc3 vmm: Fix compilation on aarch64 MSHV
Certain MSHV ioctls are only available on x86 architecture. Thus,
conditionally compile seccomp filter for x86 and in general enable
seccomp filters when compiling for MSHV on aarch64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-03-21 03:50:59 +00:00
Philipp Schuster
fa58b725cb vmm: alphabetically sort CLI options in --help output
The CLI has grown to a big variety of options. clap prints them in the
help message (--help) in the order they were defined. We now are at a
point where grouping things logically together doesn't work well.
Further, there is no support by clap for logical grouping and the
current code base wasn't consistent. Therefore, this commit introduces
two changes:

- a new structure to define arguments (all in an array)
- an alphabetical ordering of the arguments

No other changes have been made. No options have been altered.

This significantly improves:
- code maintainability and extensibility
- readability of the --help output

A unit test ensures they stay sorted. A better approach to check if the
list of arguments (known at build time) is sorted would be a compile
time check (`const`), but this currently isn't possible in stable Rust.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-03-20 08:43:09 +00:00
Andrew Consroe
a38b4c7f17 vmm: tighten landlock rule for PmemConfig
when discard_writes is true, only grant read access in landlock

Signed-off-by: Andrew Consroe <aconz2@gmail.com>
2025-03-20 01:58:10 +00:00
Philipp Schuster
5aa1540c5d ci: gitlint now ignores long lines from links
This helps to prevent annoying CI failures when one adds useful resources into
a commit message, such as [0].

One can test this locally using: `gitlint --commits HEAD~1..HEAD`

[0]
https://example.com/?lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum-lorem-ipsum

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-03-19 16:11:26 +00:00
Jinank Jain
7da8ae9c0f hypervisor: Fix MSHV compilation on aarch64
Use the definitions from the rust-vmm/mshv crate for various
datastructures such as StandardRegisters, RegList, VcpuInit etc.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-03-19 06:58:52 +00:00
Wei Liu
108e8f9dff hypervisor: mshv: handle cross-page access in emulator
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-03-17 21:40:24 +00:00
dependabot[bot]
5ab2feae70 build: Bump anstyle-query from 1.1.1 to 1.1.2
Bumps [anstyle-query](https://github.com/rust-cli/anstyle) from 1.1.1 to 1.1.2.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.1...anstyle-query-v1.1.2)

---
updated-dependencies:
- dependency-name: anstyle-query
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-15 00:15:13 +00:00
Ruoqing He
c99660a8f9 vmm: Introduce riscv64 architecture support
Integrate all works done previously to enable booting riscv linux on
riscv platforms, example command:

```console
./target/debug/cloud-hypervisor \
        --kernel path/to/kernel \
        --disk path=path/to/disk \
        --cmdline "console=hvc0 root=/dev/vda rw" \
        --cpus boot=1 \
        --memory size=1024M \
        --seccomp false
```

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-14 17:00:57 +00:00
Ruoqing He
08c1bb4b00 ci: Enable retry for Link Check
Link check is likely to fail due to connectivity reasons, retry three
times before it fails.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-14 16:56:12 +00:00
Bo Chen
5bd177dde8 ci: Move metrics and rate-limiter workers
We are moving the metrics and rate-limiter workers to a bare-metal
system, so that we can have more consistent results (particularly for
the block device metrics)

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-03-14 10:15:21 +00:00
dependabot[bot]
52ed1082fb build: Bump igvm from 0.3.3 to 0.3.4
Bumps [igvm](https://github.com/microsoft/igvm) from 0.3.3 to 0.3.4.
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](https://github.com/microsoft/igvm/compare/igvm-v0.3.3...igvm-v0.3.4)

---
updated-dependencies:
- dependency-name: igvm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-14 00:28:53 +00:00
dependabot[bot]
03a23309b9 build: Bump async-channel from 2.3.0 to 2.3.1
Bumps [async-channel](https://github.com/smol-rs/async-channel) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/smol-rs/async-channel/releases)
- [Changelog](https://github.com/smol-rs/async-channel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-channel/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: async-channel
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-13 01:45:20 +00:00
dependabot[bot]
fa0965a11a build: Bump indexmap from 2.7.1 to 2.8.0
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.7.1 to 2.8.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-12 00:02:27 +00:00
Anatol Belski
524f26abef vmm: api: Expose SEV-SNP and igvm related options
This involves the platform  and VM config.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-03-11 17:22:20 +00:00
dependabot[bot]
846d0976e3 build: Bump unicode-ident from 1.0.12 to 1.0.18
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.12 to 1.0.18.
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.12...1.0.18)

---
updated-dependencies:
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-11 00:33:12 +00:00
Ruoqing He
4718dc1b72 build: Manually bump seccompiler to 0.5.0
v0.5.0 of `seccompiler` has supported riscv64, let's bump from v0.4.0 to
v0.5.0 to capture that support.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-10 17:38:56 +00:00
dependabot[bot]
0a9895e009 build: Bump ryu from 1.0.18 to 1.0.20
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.18 to 1.0.20.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.20)

---
updated-dependencies:
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 09:43:34 +00:00
Bo Chen
297b41d615 pci, vmm: vfio: Report device path on host with DMA map/unmap errors
In addition to the BDF information on the guest, reporting the device
path of the VFIO device on the host is more useful when it comes to
debug DMA map/unmap errors particularly ones caused by failing hardware
on the host.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-03-08 10:00:34 +00:00
Ruoqing He
396aba7a52 tests: Skip test_snapshot_restore_with_fd on aarch64
`test_snapshot_restore_with_fd` uses unsafe file descriptors and with
rust 1.82.0 it errors with:

```
fatal runtime error: IO Safety violation: owned file descriptor already
closed
```

so has been skipped for now.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-07 15:09:14 +00:00
Ruoqing He
35aaa1333a misc: Fix clippy - more concise repeat().take()
Reported by 1.86.0-beta.1 (f0cb41030 2025-02-17).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-07 15:09:14 +00:00
Ruoqing He
6768a13d95 build: Bump MSRV to 1.82.0
We are having complains from Rust 1.86.0-beta.1 (f0cb41030 2025-02-17)'
clippy, which suggests us to replace `repeat().take()` with
`repeat_n()`. While `repeat_n()` is stablized in Rust 1.82.0.

Update image to 20250307-2 because MSRV in Dockerfile is updated.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-07 15:09:14 +00:00
Ruoqing He
0d50d0b257 build: Add force-non-host to install minimal toolchain
While executing `rustup toolchain add --profile minimal
1.82.0-x86_64-unknown-linux-musl`, it errors out with:

```
error: toolchain '1.82.0-x86_64-unknown-linux-musl' may not be able to
run on this system
note: add the `--force-non-host` flag to install the toolchain anyway
```

Add `--force-non-host` to install minimal musl toolchain for x86_64.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-07 15:09:14 +00:00
Jinank Jain
f5a2f8473b hypervisor: Add a basic implementation of MshvVcpuState for aarch64
Currently we are just storing the StandardRegisters in the Vcpu state
which would be required for saving and restoring the ARM64 guest on
MSHV.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-03-06 11:14:16 +00:00
Stefan Kober
03bb59db69 seccomp: Allow clock_gettime() on http api thread
Signed-off-by: Stefan Kober <stefan.kober@cyberus-technology.de>
2025-03-05 15:35:37 +00:00
Ruoqing He
9e1fb3bfa1 misc: Fix clippy - manual implementation of ok
Reported by 1.86.0-beta.1 (f0cb41030 2025-02-17).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-01 01:02:17 +00:00
Ruoqing He
4de422ad69 misc: Fix clippy - manually reimplementing div_ceil
Reported by 1.86.0-beta.1 (f0cb41030 2025-02-17).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-01 01:02:17 +00:00
Ruoqing He
c441bb2968 misc: Fix clippy - doc list item overindented
Reported by 1.86.0-beta.1 (f0cb41030 2025-02-17).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-01 01:02:17 +00:00
Ruoqing He
5cb5115456 build: Fix spdk in linux/arm64 image
The reason `test_vfio_user` fails is as @likebreath pointed: our ARM
host does not support SVE, while the nvme_tgt binary built from the
container image requires it. As a result, we encountered a SIGILL when
running the nvme_tgt binary. This also explains why this is not
happening when the container is built on the same host itself.

And quote from @rbradford:

When a job is run on one of the workers it looks to see if there is a
container locally matching the name as specified in the dev_cli.sh
script - if there is then it uses it. Otherwise it will try and download
it from the container registry - if that fails then it will built
locally. For the x86-64 workers started dynamically it will never have a
local version as they are a fresh VM. But on the ARM64 builder is a
local container image cache.

This can lead to an issue where if the image is build with one version
(a handcrafted datestamp) and then the Dockerfile is changed without
changing the timestamp then an old version may be fetched from the cache
or server. It is there for essential to always bump the datestamp (there
is a number after the - that can be used for this.)

However there is also the added complexity that image that is build and
uploaded to the container registry is not the same as the built locally
and thus used for the initial testing of the Dockerfile change. This
leads to the issue we have seen where different CPU compiler flags (from
-march=native) from the QEMU cross build in the hosted GHA action and
the local ARM64 build. Resulting in a binary in the remotely built
container not working locally.

We end up specifying TARGET_ARCHITECTURE="armv8.2-a" for building spdk,
and put built `python/spdk/` folder into `/usr/local/bin/spdk-nvme`.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-28 18:34:23 +00:00
Ruoqing He
0fbba66b21 scripts: Remove SPDK build in aarch64 test script
We already build `SPDK` for `linux/arm64` in our `Dockerfile`, no need
to build it here anymore.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-24 14:41:46 +00:00
Ruoqing He
5388fa1ced build: Build SPDK for arm64 docker image
Enable `SPDK` build (with DPDK for `generic` arm64 platform) for
`linux/arm64` image.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-24 14:41:46 +00:00
Ruoqing He
655d512523 build: Upgrade to 24.04 in Dockerfile
`arm64` build in ubuntu:22.04 errors out with `error processing package
libc-bin`. This issue is a known issue between the binfmt (running
different architectures via QEMU) and the libc ldconfig binary running
in container. We're "suddenly" having issues as ubuntu-latest (which is
the OS version we run the GH action container with) was recently changed
from 22.04 to 24.04 and hence why upgrading the container userspace from
22.04 to 24.04 solves the problem.

Removed deprecated package `python3-distutils`.

Update image name from `20250111-0` to `20250222-0`.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-24 14:41:46 +00:00
Ruoqing He
7d45473ff7 ci: Update docker actions to latest
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-24 14:41:46 +00:00
Ruoqing He
294d5fbb08 misc: Fix clippy - operator precedence can trip the unwary
Reported by 1.85.0-stable (4d91de4e4 2025-02-17), fix accordingly.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-21 23:15:04 +00:00
Jinank Jain
8c796e6d5d hypervisor: Add MSHV implementation of VcpuInit
Extend the VcpuInit interface to accomodate changes for MSHV on aarch64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-19 23:23:45 +00:00
Jinank Jain
630f5c1f14 hypervisor: Add MSHV implementation of RegList
Extend the RegList interface to accomodate changes for MSHV on aarch64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-19 23:23:45 +00:00
Jinank Jain
5cbf907200 hypervisor: Add implementation to fetch host IPA limit on MSHV
This fixes an compilation error when we try to compile CloudHypervisor
for MSHV on aarch64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-19 09:39:21 +00:00
dependabot[bot]
bfeab76059 build: Bump async-trait from 0.1.85 to 0.1.86
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.85 to 0.1.86.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.85...0.1.86)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-19 04:30:55 +00:00
dependabot[bot]
12143ca72f build: Bump proc-macro2 from 1.0.92 to 1.0.93
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.92 to 1.0.93.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.92...1.0.93)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-18 00:27:36 +00:00
dependabot[bot]
ba05bdd085 build: Bump proc-macro-crate from 3.1.0 to 3.2.0
Bumps [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/bkchr/proc-macro-crate/releases)
- [Commits](https://github.com/bkchr/proc-macro-crate/commits/v3.2.0)

---
updated-dependencies:
- dependency-name: proc-macro-crate
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 12:07:24 +00:00
Jinank Jain
171b28ce52 hypervisor, vmm: Avoid leaking hypervisor specific data structure
Currently a bunch of KVM specific interfaces are leaked into the vmm
crate which should ideally does not contain any hypervisor specific data
structures.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-12 23:08:43 +00:00
Jinank Jain
5b929cb277 hypervisor: Implement hypervisor agnostic variant of VcpuInit
This will help in fixing the build issue for MSHV on ARM64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-12 23:08:43 +00:00
Jinank Jain
ee0b0d43d8 hypervisor: Implement hypervisor agnostic variant of RegList
This helps in unification of RegList across different platforms.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-12 23:08:43 +00:00
Jinank Jain
061482340e hypervisor: Implement hypervisor agnostic Register interface
This will help in fixing the build issue for MSHV on ARM64.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-12 23:08:43 +00:00
dependabot[bot]
c43ae1dc9d build: Bump dirs from 5.0.1 to 6.0.0
Bumps [dirs](https://github.com/soc/dirs-rs) from 5.0.1 to 6.0.0.
- [Commits](https://github.com/soc/dirs-rs/commits)

---
updated-dependencies:
- dependency-name: dirs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-11 23:57:37 +00:00
Jinank Jain
7db3002e1d build: Bump mshv crate to latest version
Move mshv crates from v0.3.2 to v0.3.3

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-02-11 14:31:48 +00:00
Ruoqing He
07b7457c2e build: Bump getrandom from 0.2.15 to 0.3.1
Manually bump `getrandom` due to API changes.

Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.2.15 to 0.3.1.
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](rust-random/getrandom@v0.2.15...v0.3.1)

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-11 07:40:16 +08:00
Ruoqing He
dc9142f86c ci: Introduce lychee to check links
Use `lychee` to check availability of links in cloud-hypervisor.

The urls explictly excluded in config file are manually checked.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 22:11:19 +08:00
Ruoqing He
6fa7c84d2e misc: Update link in release-note.md
We have lost track to releases before v27.0 since these projects no
longer exists. Delete links to those projects.

Update links to a detailed view specific to each group of release.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 17:32:54 +08:00
Ruoqing He
cc734e2e44 docs: Fix broken to fedora 36 artifacts
Content of fedora 36 have been moved to fedora archives [1], update
accordingly.

Format `README.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

[1] http://archives.fedoraproject.org/pub/archive/fedora/

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:47:14 +08:00
Ruoqing He
e3e83362d6 docs: Fix broken link in CONTRIBUTING.md
Previous repo hosts details of `Rust Style` is removed, point `Rust
Style` to `style-guide` in `rust-lang/rust` repo.

Link to provide illustration on `signed-off-by language` is also
removed, use a snapshot found in web archive [1] instead.

Format `CONTRIBUTING.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

[1] https://web.archive.org

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:40:57 +08:00
Ruoqing He
730cf1e944 docs: Fix broken link to intel 0x80 debug port
Previous link to provide details of `0x80 debug port` is removed, which
could no longer be found on intel site [1]. Use snapshot found in web
archive [2] to fix this link.

Format `debug-port.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

[1] https://www.intel.com/content/www/us/en/homepage.html
[2] https://web.archive.org

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:40:44 +08:00
Ruoqing He
1caa69d0cc docs: Update outdated intel_sgx.md
TDX homepage was moved to elsewhere, and `sgx` support is upstreamed
since v5.11 kernel.

Format `intel_sgx.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:39:16 +08:00
Ruoqing He
abcbf43433 docs: Update outdated intel_tdx.md
TDX homepage was moved to elsewhere, and `tdx-tools` repo was removed.

Provide a valid link of TDX homepage and change all reference to
`tdx-tools` to `tdx-linux`.

Format `intel_tdx.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:38:46 +08:00
Ruoqing He
af74de2779 docs: Fix broken link in io_throttling.md
There is a link referencing `rate-limiter` module of `firecracker`, but
that module no longer exsits.

Point the link to a commit with the same date in `firecracker` when this
commit was merged to `cloud-hypervisor`.

Format `io_throttling.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:38:22 +08:00
Ruoqing He
dfebc8929d docs: Fix broken link to docs/arm64.md
`docs/arm64.md` was removed and splited into `README.md`, `building.md`
and `uefi.md` in #4991.

Let's point it to
`8ab15b9a98/docs/arm64.md`
the commit right before `docs/arm64.md` was removed in main branch.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:37:50 +08:00
Ruoqing He
9988379f6b docs: Fix link to docs/logging.md
Previous link `docs/logging` is not valid, replacing `docs/logging` with
`docs/logging.md`.

Format `logging.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:37:03 +08:00
Ruoqing He
4d12192490 docs: Fix broken link in amd_sev_snp.md
Previous link to details of SNP is now broken, pointing that section to
a valid link [1].

Format `amd_sev_snp.md` using `mdformat` with GitHub Flavored Markdown
(GFM).

[1] https://www.amd.com/content/dam/amd/en/documents/epyc-business-docs/solution-briefs/amd-secure-encrypted-virtualization-solution-brief.pdf

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-02-08 16:36:48 +08:00
Wei Liu
9f9cfeb5be build: Provide CH_EXTRA_VERSION
Use this to add any extra versioning information to the binary. It is
useful when packaging Cloud Hypervisor.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-02-04 19:33:10 +00:00
63 changed files with 1732 additions and 1527 deletions

View File

@@ -15,7 +15,7 @@ jobs:
- stable
- beta
- nightly
- "1.77.0"
- "1.82.0"
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl

View File

@@ -21,13 +21,13 @@ jobs:
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
- name: Login to ghcr
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -36,17 +36,17 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=20250111-0
type=raw,value=20250307-2
type=sha
- name: Build and push
if: ${{ github.event_name == 'push' }}
uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with:
file: ./resources/Dockerfile
platforms: linux/amd64,linux/arm64
@@ -55,7 +55,7 @@ jobs:
- name: Build only
if: ${{ github.event_name == 'pull_request' }}
uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with:
file: ./resources/Dockerfile
platforms: linux/amd64,linux/arm64

View File

@@ -7,7 +7,7 @@ on:
jobs:
build:
name: Tests (Metrics)
runs-on: garm-jammy-16
runs-on: bare-metal-9950x
env:
METRICS_PUBLISH_KEY: ${{ secrets.METRICS_PUBLISH_KEY }}
steps:
@@ -15,15 +15,6 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Docker
run: |
sudo apt-get update
sudo apt-get -y install ca-certificates curl gnupg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-ce-cli
- name: Run metrics tests
timeout-minutes: 60
run: scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json

View File

@@ -7,7 +7,7 @@ concurrency:
jobs:
build:
name: Tests (Rate-Limiter)
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'garm-jammy-16' }}
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'bare-metal-9950x' }}
env:
AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
steps:
@@ -16,16 +16,6 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Docker
if: ${{ github.event_name != 'pull_request' }}
run: |
sudo apt-get update
sudo apt-get -y install ca-certificates curl gnupg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-ce-cli
- name: Run rate-limiter integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 20

16
.github/workflows/lychee.yaml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Link Check (lychee)
on:
pull_request
jobs:
link_check:
name: Link Check
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Link Availability Check
uses: lycheeverse/lychee-action@master
with:
args: --verbose --config .lychee.toml .

View File

@@ -24,7 +24,7 @@ jobs:
fetch-depth: 0
- name: Install Rust toolchain
run: /opt/scripts/exec-in-qemu.sh rustup default 1.77.0
run: /opt/scripts/exec-in-qemu.sh rustup default 1.82.0
- name: Build ${{ matrix.module }} Module (kvm)
run: /opt/scripts/exec-in-qemu.sh cargo rustc --locked -p ${{ matrix.module }} --no-default-features --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states

View File

@@ -45,7 +45,7 @@ jobs:
target: ${{ matrix.platform.target }}
args: ${{ matrix.platform.args }}
strip: true
toolchain: "1.77.0"
toolchain: "1.82.0"
- name: Copy Release Binaries
if: github.event_name == 'create' && github.event.ref_type == 'tag'
shell: bash

View File

@@ -13,3 +13,8 @@ line-length=72
# default 80
[body-max-line-length]
line-length=72
# Allow developers to add long links to useful resources
[ignore-by-body]
regex=^https?:\/\/
ignore=body-max-line-length

18
.lychee.toml Normal file
View File

@@ -0,0 +1,18 @@
verbose = "info"
exclude = [
# Availability of links below should be manually verified.
# Page for intel SGX support, returns 403 while querying.
'^https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/linux-overview.html',
# Page for intel TDX support, returns 403 while querying.
'^https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/overview.html',
# Page for TPM, returns 403 while querying.
'^https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf',
# GitHub user smibarber referenced in `CREDITS.md` no longer exist
'^https://github.com/smibarber',
]
max_retries = 3
retry_wait_time = 5

View File

@@ -13,7 +13,7 @@ License](https://opensource.org/licenses/Apache-2.0).
## Coding Style
We follow the [Rust Style](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md)
We follow the [Rust Style](https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src)
convention and enforce it through the Continuous Integration (CI) process calling into `rustfmt`
for each submitted Pull Request (PR).
@@ -36,7 +36,7 @@ commit you make.
## Certificate of Origin
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://01.org/community/signed-process)
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://web.archive.org/web/20230406041855/https://01.org/community/signed-process)
used by the Linux kernel project.
## Patch format
@@ -79,12 +79,12 @@ you want to merge your changes to `cloud-hypervisor`:
1. Fork the [cloud-hypervisor](https://github.com/cloud-hypervisor/cloud-hypervisor) project
into your github organization.
2. Within your fork, create a branch for your contribution.
3. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
1. Within your fork, create a branch for your contribution.
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
against the main branch of the Cloud Hypervisor repository.
4. To update your pull request amend existing commits whenever applicable and
1. To update your pull request amend existing commits whenever applicable and
then push the new changes to your pull request branch.
5. Once the pull request is approved it can be integrated.
1. Once the pull request is approved it can be integrated.
## Issue tracking

131
Cargo.lock generated
View File

@@ -66,11 +66,11 @@ dependencies = [
[[package]]
name = "anstyle-query"
version = "1.1.1"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -137,12 +137,11 @@ dependencies = [
[[package]]
name = "async-channel"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f2776ead772134d55b62dd45e59a79e21612d85d0af729b8b7d3967d601a62a"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
dependencies = [
"concurrent-queue",
"event-listener",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
@@ -258,9 +257,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
version = "0.1.85"
version = "0.1.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
dependencies = [
"proc-macro2",
"quote",
@@ -420,7 +419,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "cloud-hypervisor"
version = "44.0.0"
version = "45.0.0"
dependencies = [
"anyhow",
"api_client",
@@ -611,23 +610,23 @@ dependencies = [
[[package]]
name = "dirs"
version = "5.0.1"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -913,10 +912,22 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
name = "getrandom"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets 0.52.6",
]
[[package]]
name = "gimli"
version = "0.31.1"
@@ -931,9 +942,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.14.5"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "hermit-abi"
@@ -997,9 +1008,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "igvm"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7984b10433b50e06a06bd50c69bca4888a5d7de8975f64ea4c2a7687eb99b09d"
checksum = "7b4ae8479aa3163c8a0fa716aa6ef08a6553e1097f8a89544f46fee695b5a162"
dependencies = [
"bitfield-struct",
"crc32fast",
@@ -1014,9 +1025,9 @@ dependencies = [
[[package]]
name = "igvm_defs"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64ec5588c475372ae830475d3ee9a7bd255407dcb9f03faf6d493556eb6105a"
checksum = "e4f70c18b574e5c7fa6222c1f0ebd8bfe2e14b762573b799faf8697c044b0e2a"
dependencies = [
"bitfield-struct",
"open-enum",
@@ -1026,9 +1037,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.2.6"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
dependencies = [
"equivalent",
"hashbrown",
@@ -1243,9 +1254,9 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07"
[[package]]
name = "mshv-bindings"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0cb5031f3243a7459b7c13d960d25420980874eebda816db24ce6077e21d43"
checksum = "30f83f36cb864d90b62a4576556cef3319603d02f3aca58a87694e1e0694bdda"
dependencies = [
"libc",
"num_enum",
@@ -1257,9 +1268,9 @@ dependencies = [
[[package]]
name = "mshv-ioctls"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89abe853221fa6f14ad4066affb9abda241a03d65622887d5794e1422d0bd75a"
checksum = "7cd6d081aa1eb9916b8f2ac89a6f22adaaa9b5308c71ff5f14332143dc52aaf6"
dependencies = [
"libc",
"mshv-bindings",
@@ -1273,7 +1284,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
dependencies = [
"getrandom",
"getrandom 0.2.15",
]
[[package]]
@@ -1288,7 +1299,7 @@ name = "net_util"
version = "0.1.0"
dependencies = [
"epoll",
"getrandom",
"getrandom 0.3.1",
"libc",
"log",
"net_gen",
@@ -1672,18 +1683,18 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@@ -1724,7 +1735,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
"getrandom 0.2.15",
]
[[package]]
@@ -1764,13 +1775,13 @@ dependencies = [
[[package]]
name = "redox_users"
version = "0.4.6"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [
"getrandom",
"getrandom 0.2.15",
"libredox",
"thiserror 1.0.62",
"thiserror 2.0.6",
]
[[package]]
@@ -1840,9 +1851,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.18"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "scopeguard"
@@ -1852,9 +1863,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "seccompiler"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345a3e4dddf721a478089d4697b83c6c0a8f5bf16086f6c13397e4534eb6e2e5"
checksum = "a4ae55de56877481d112a559bbc12667635fdaf5e005712fd4e2b2fa50ffc884"
dependencies = [
"libc",
]
@@ -2103,15 +2114,15 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
[[package]]
name = "toml_datetime"
version = "0.6.5"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
[[package]]
name = "toml_edit"
version = "0.21.1"
version = "0.22.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
dependencies = [
"indexmap",
"toml_datetime",
@@ -2192,9 +2203,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
@@ -2208,7 +2219,7 @@ version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
dependencies = [
"getrandom",
"getrandom 0.2.15",
"rand",
"uuid-macro-internal",
]
@@ -2539,6 +2550,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
@@ -2765,13 +2785,22 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.5.40"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "xdg-home"
version = "1.3.0"

View File

@@ -7,7 +7,7 @@ edition = "2021"
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
license = "Apache-2.0 AND BSD-3-Clause"
name = "cloud-hypervisor"
version = "44.0.0"
version = "45.0.0"
# Minimum buildable version:
# Keep in sync with version in .github/workflows/build.yaml
# Policy on MSRV (see #4318):
@@ -15,7 +15,7 @@ version = "44.0.0"
# a.) A dependency requires it,
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
# c.) There is a security issue that is addressed by the toolchain update.
rust-version = "1.77.0"
rust-version = "1.82.0"
[profile.release]
codegen-units = 1
@@ -51,7 +51,7 @@ vmm-sys-util = { workspace = true }
zbus = { version = "4.4.0", optional = true }
[dev-dependencies]
dirs = "5.0.1"
dirs = "6.0.0"
net_util = { path = "net_util" }
once_cell = "1.20.2"
serde_json = "1.0.120"
@@ -102,13 +102,14 @@ members = [
]
[workspace.dependencies]
# rust-vmm crates
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
kvm-bindings = "0.10.0"
kvm-ioctls = "0.19.1"
linux-loader = "0.13.0"
mshv-bindings = "0.3.2"
mshv-ioctls = "0.3.2"
seccompiler = "0.4.0"
mshv-bindings = "0.3.3"
mshv-ioctls = "0.3.3"
seccompiler = "0.5.0"
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main" }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
@@ -119,3 +120,7 @@ virtio-queue = "0.14.0"
vm-fdt = { git = "https://github.com/rust-vmm/vm-fdt", branch = "main" }
vm-memory = "0.16.1"
vmm-sys-util = "0.12.1"
# igvm crates
igvm = "0.3.4"
igvm_defs = "0.3.1"

View File

@@ -59,9 +59,13 @@ based on the [Rust VMM](https://github.com/rust-vmm) crates.
### Architectures
Cloud Hypervisor supports the `x86-64` and `AArch64` architectures. There are
minor differences in functionality between the two architectures
(see [#1125](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1125)).
Cloud Hypervisor supports the `x86-64`, `AArch64` and `riscv64`
architectures, with functionality varying across these platforms. The
functionality differences between `x86-64` and `AArch64` are documented
in [#1125](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1125).
The `riscv64` architecture support is experimental and offers limited
functionality. For more details and instructions, please refer to [riscv
documentation](docs/riscv.md).
### Guest OS
@@ -298,7 +302,7 @@ As of 2023-01-03, the following cloud images are supported:
- [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (focal-server-cloudimg-{amd64,arm64}.img)
- [Ubuntu Jammy](https://cloud-images.ubuntu.com/jammy/current/) (jammy-server-cloudimg-{amd64,arm64}.img )
- [Fedora 36](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/) ([Fedora-Cloud-Base-36-1.5.x86_64.raw.xz](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/x86_64/images/) / [Fedora-Cloud-Base-36-1.5.aarch64.raw.xz](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/aarch64/images/))
- [Fedora 36](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/) ([Fedora-Cloud-Base-36-1.5.x86_64.raw.xz](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/x86_64/images/) / [Fedora-Cloud-Base-36-1.5.aarch64.raw.xz](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/aarch64/images/))
Direct kernel boot to userspace should work with a rootfs from most
distributions although you may need to enable exotic filesystem types in the

View File

@@ -1109,10 +1109,7 @@ fn print_node(node: fdt_parser::node::FdtNode<'_, '_>, n_spaces: usize) {
// - At first, try to convert it to CStr and print,
// - If failed, print it as u32 array.
let value_result = match CStr::from_bytes_with_nul(value) {
Ok(value_cstr) => match value_cstr.to_str() {
Ok(value_str) => Some(value_str),
Err(_e) => None,
},
Ok(value_cstr) => value_cstr.to_str().ok(),
Err(_e) => None,
};

View File

@@ -747,12 +747,12 @@ pub fn generate_common_cpuid(
// These features are not supported by TDX
#[cfg(feature = "tdx")]
if config.tdx {
entry.eax &= !(1 << KVM_FEATURE_CLOCKSOURCE_BIT
| 1 << KVM_FEATURE_CLOCKSOURCE2_BIT
| 1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT
| 1 << KVM_FEATURE_ASYNC_PF_BIT
| 1 << KVM_FEATURE_ASYNC_PF_VMEXIT_BIT
| 1 << KVM_FEATURE_STEAL_TIME_BIT)
entry.eax &= !((1 << KVM_FEATURE_CLOCKSOURCE_BIT)
| (1 << KVM_FEATURE_CLOCKSOURCE2_BIT)
| (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)
| (1 << KVM_FEATURE_ASYNC_PF_BIT)
| (1 << KVM_FEATURE_ASYNC_PF_VMEXIT_BIT)
| (1 << KVM_FEATURE_STEAL_TIME_BIT))
}
}
_ => {}

View File

@@ -299,7 +299,7 @@ pub struct TdHob {
}
fn align_hob(v: u64) -> u64 {
(v + 7) / 8 * 8
v.div_ceil(8) * 8
}
impl TdHob {

View File

@@ -502,7 +502,7 @@ impl QcowFile {
if refcount_bits != 16 {
return Err(Error::UnsupportedRefcountOrder);
}
let refcount_bytes = (refcount_bits + 7) / 8;
let refcount_bytes = refcount_bits.div_ceil(8);
// Need at least one refcount cluster
if header.refcount_table_clusters == 0 {

View File

@@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::env;
use std::process::Command;
fn main() {
@@ -12,10 +13,18 @@ fn main() {
if git_out.status.success() {
if let Ok(git_out_str) = String::from_utf8(git_out.stdout) {
version = git_out_str;
// Pop the trailing newline.
version.pop();
}
}
}
// Append CH_EXTRA_VERSION to version if it is set.
if let Ok(extra_version) = env::var("CH_EXTRA_VERSION") {
println!("cargo:rerun-if-env-changed=CH_EXTRA_VERSION");
version.push_str(&format!("-{}", extra_version));
}
// This println!() has a special behavior, as it will set the environment
// variable BUILD_VERSION, so that it can be reused from the binary.
// Particularly, this is used from src/main.rs to display the exact

View File

@@ -1,6 +1,7 @@
# AMD SEV-SNP
### WARNING
This feature is only currently supported on MSHV.
AMD Secure Encrypted Virtualization & Secure Nested Paging (SEV-SNP) is an AMD
@@ -9,8 +10,8 @@ malicious hypervisor-based attacks like data replay, memory-remapping and more
in order to create an isolated execution environment. Here are some useful
links:
* [SNP Homepage] (https://www.amd.com/en/processors/amd-secure-encrypted-virtualization)
more information about SEV-SNP technical aspects, design and specification.
- [SNP Homepage](https://www.amd.com/content/dam/amd/en/documents/epyc-business-docs/solution-briefs/amd-secure-encrypted-virtualization-solution-brief.pdf):
more information about SEV-SNP technical aspects, design and specification.
## Cloud Hypervisor support

View File

@@ -1,8 +1,9 @@
# `cloud-hypervisor` debug IO ports
When running x86 guests, `cloud-hypervisor` provides different kinds of debug ports:
- [`0x80` debug port](https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
- Debug console (by default at `0xe9`).
- [`0x80` debug port](https://web.archive.org/web/20211028033025/https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
- Debug console (by default at `0xe9`).
- Firmware debug port at `0x402`.
All of them can be used to trace user-defined guest events and all of them can
@@ -25,13 +26,13 @@ for debugging specific components of the guest software stack. When logging a
write of one of those codes to the debug port, `cloud-hypervisor` adds a
pre-defined string to the logs.
| Code Range | Component | Log string |
| ---------------- | ----------- | ------------ |
| `0x00` to `0x1f` | Firmware | `Firmware` |
| `0x20` to `0x3f` | Bootloader | `Bootloader` |
| `0x40` to `0x5f` | Kernel | `Kernel` |
| `0x60` to `0x7f` | Userspace | `Userspace` |
| `0x80` to `0xff` | Custom | `Custom` |
| Code Range | Component | Log string |
| ---------------- | ---------- | ------------ |
| `0x00` to `0x1f` | Firmware | `Firmware` |
| `0x20` to `0x3f` | Bootloader | `Bootloader` |
| `0x40` to `0x5f` | Kernel | `Kernel` |
| `0x60` to `0x7f` | Userspace | `Userspace` |
| `0x80` to `0xff` | Custom | `Custom` |
One typical use case is guest boot time measurement and tracing. By writing
different values to the debug I/O port at different boot process steps, the
@@ -71,8 +72,8 @@ cloud-hypervisor: 403.499628ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firm
### Debug console port
The debug console is inspired by QEMU and Bochs, which have a similar feature.
By default, the I/O port `0xe9` is used. This port can be configured like a
The debug console is inspired by QEMU and Bochs, which have a similar feature.
By default, the I/O port `0xe9` is used. This port can be configured like a
console. Thus, it can print to a tty, a file, or a pty, for example.
### Firmware debug port
@@ -83,7 +84,7 @@ it. The firmware debug port only prints to stdout.
## When do I need these ports?
The ports are on the one hand interesting for firmware or kernel developers, as
they provide an easy way to print debug information from within a guest.
they provide an easy way to print debug information from within a guest.
Furthermore, you can patch "normal" software to measure certain events, such as
the boot time of a guest.
@@ -91,6 +92,6 @@ the boot time of a guest.
The `0x80` debug port and the port of the firmware debug device are always
available. The debug console must be activated via the command line, but
provides more configuration options.
provides more configuration options.
You can use different ports for different aspect of your logging messages.
You can use different ports for different aspect of your logging messages.

View File

@@ -8,11 +8,12 @@ the host kernel. The required Linux and KVM changes can be found in the
[KVM SGX Tree](https://github.com/intel/kvm-sgx).
Utilizing SGX in the guest requires a kernel/OS with SGX support, e.g. a kernel
built using the [SGX Linux Development Tree](https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-sgx.git)
since release 5.11, see
[here](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/linux-overview.html)
or the [KVM SGX Tree](https://github.com/intel/kvm-sgx). Running KVM SGX as the
guest kernel allows nested virtualization of SGX.
For more information about SGX, please refer to the [SGX Homepage](https://software.intel.com/sgx).
For more information about SGX, please refer to the [SGX Homepage](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/linux-overview.html).
For more information about SGX SDK and how to test SGX, please refer to the
following [instructions](https://github.com/intel/linux-sgx).

View File

@@ -4,21 +4,21 @@ Intel® Trust Domain Extensions (Intel® TDX) is an Intel technology designed to
isolate virtual machines from the VMM, hypervisor and any other software on the
host platform. Here are some useful links:
* [TDX Homepage](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html):
more information about TDX technical aspects, design and specification
- [TDX Homepage](https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/overview.html):
more information about TDX technical aspects, design and specification
* [KVM TDX tree](https://github.com/intel/tdx/tree/kvm): the required
- [KVM TDX tree](https://github.com/intel/tdx/tree/kvm): the required
Linux kernel changes for the host side
* [Guest TDX tree](https://github.com/intel/tdx/tree/guest): the Linux
- [Guest TDX tree](https://github.com/intel/tdx/tree/guest): the Linux
kernel changes for the guest side
* [EDK2 project](https://github.com/tianocore/edk2): the TDVF firmware
- [EDK2 project](https://github.com/tianocore/edk2): the TDVF firmware
* [Confidential Containers project](https://github.com/confidential-containers/td-shim):
- [Confidential Containers project](https://github.com/confidential-containers/td-shim):
the TDShim firmware
* [TDX Tools](https://github.com/intel/tdx-tools): a collection of tools
- [TDX Linux](https://github.com/intel/tdx-linux): a collection of tools
and scripts to setup TDX environment for testing purpose (such as
installing required packages on the host, creating guest images, and
building the custom Linux kernel for TDX host and guest)
@@ -27,17 +27,13 @@ more information about TDX technical aspects, design and specification
It is required to use a machine with TDX enabled in hardware and
with the host OS compiled from the [KVM TDX tree](https://github.com/intel/tdx/tree/kvm).
The host environment can also be setup with the [TDX Tools](https://github.com/intel/tdx-tools).
The host environment can also be setup with the [TDX Linux](https://github.com/intel/tdx-linux).
Cloud Hypervisor can run TDX VM (Trust Domain) by loading a TD firmware ([TDVF](https://github.com/tianocore/edk2)),
which will then load the guest kernel from the image. The image must be custom
as it must include a kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
Cloud Hypervisor can also boot a TDX VM with direct kernel boot using [TDshim](https://github.com/confidential-containers/td-shim).
The custom Linux kernel for the guest can be built with the [TDX Tools](https://github.com/intel/tdx-tools).
> **Note**
> The latest version of custom host and guest kernel being tested is
> from [TDX Tools - 2023ww01](https://github.com/intel/tdx-tools/commits/2023ww01).
The custom Linux kernel for the guest can be built with the [TDX Linux](https://github.com/intel/tdx-linux).
### TDVF
@@ -110,6 +106,7 @@ direct kernel boot, which is useful for containers use cases.
To build TDShim from source, it is required to install `Rust`, `NASM`,
and `LLVM` first. The TDshim can be build as follows:
```bash
git clone https://github.com/confidential-containers/td-shim
cd td-shim
@@ -126,13 +123,14 @@ cargo image --release
If debug logs from the TDShim is needed, here are the alternative
commands:
```bash
cargo image
```
And run a TDX VM by providing the firmware previously built, along with a guest
kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest)
or the [TDX Tools](https://github.com/intel/tdx-tools).
or the [TDX Linux](https://github.com/intel/tdx-linux).
The appropriate kernel boot options must be provided through the `--cmdline`
option as well.

View File

@@ -1,7 +1,7 @@
# I/O Throttling
Cloud Hypervisor now supports I/O throttling on virtio-block and virtio-net
devices. This support is based on the [`rate-limiter` module](https://github.com/firecracker-microvm/firecracker/tree/master/src/rate_limiter)
devices. This support is based on the [`rate-limiter` module](https://github.com/firecracker-microvm/firecracker/tree/7a1231b141e958d15d5b2c079dd5e0880528b4b0/src/rate_limiter)
from Firecracker. This document explains the user interface of this
feature, and highlights some internal implementations that can help users
better understand the expected behavior of I/O throttling in practice.
@@ -44,10 +44,12 @@ generally advisable to keep `bw/ops_refill_time` larger than `100 ms`
expectation ("refill-rate").
## Rate Limit Groups
It is possible to throttle the aggregate bandwidth or operations
of multiple virtio-blk devices using a `rate_limit_group`. virtio-blk devices may be
dynamically added and removed from a `rate_limit_group`. The following example
demonstrates how to throttle the aggregate bandwidth of two disks to 10 MiB/s.
```
--disk path=disk0.raw,rate_limit_group=group0 \
path=disk1.raw,rate_limit_group=group0 \

View File

@@ -2,8 +2,8 @@
The target audience of this document is both:
* Developers who want to understand what log level to use and when,
* Users who want to debug issues with running their workloads in Cloud Hypervisor
- Developers who want to understand what log level to use and when,
- Users who want to debug issues with running their workloads in Cloud Hypervisor
## Control
@@ -29,7 +29,6 @@ A typical example of where this level of message should be generated is during a
The user should investigate the meaning of this warning and take steps to ensure the correct functionality.
### `info!()`
Use `-v` to enable.
@@ -40,4 +39,4 @@ This level is for the benefit of developers. It should be used for sporadic and
Use `-vv` to enable.
For the most verbose of logging messages. It is acceptable to "spam" the log with repeated invocations of the same message. This level of logging would be combined with `--log-file`.
For the most verbose of logging messages. It is acceptable to "spam" the log with repeated invocations of the same message. This level of logging would be combined with `--log-file`.

88
docs/riscv.md Normal file
View File

@@ -0,0 +1,88 @@
# How to build and test Cloud Hypervisor on riscv64
This document introduces how to build and test Cloud Hypervisor on `riscv64`.
All instructions here are tested with Ubuntu 24.04.2 as the host OS.
## Hardware requirements
- riscv64 servers (recommended) or development boards equipped with the AIA
(Advance Interrupt Architecture) interrupt controller.
## Getting started
We create a folder to build and run Cloud Hypervisor at `$HOME/cloud-hypervisor`
```console
export CLOUDH=$HOME/cloud-hypervisor
mkdir $CLOUDH
```
## Prerequisites
You need to install some prerequisite packages to build and test Cloud Hypervisor.
### Tools
```console
# Install rust tool chain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install the tools used for building guest kernel, EDK2 and converting guest disk
sudo apt-get update
sudo apt-get install git build-essential m4 bison flex uuid-dev qemu-utils
```
### Building Cloud Hypervisor
```console
pushd $CLOUDH
git clone https://github.com/cloud-hypervisor/cloud-hypervisor.git
cd cloud-hypervisor
cargo build
popd
```
### Disk image
Download the Ubuntu cloud image and convert the image type.
```console
pushd $CLOUDH
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-riscv64.img
qemu-img convert -p -f qcow2 -O raw jammy-server-cloudimg-riscv64.img jammy-server-cloudimg-riscv64.raw
popd
```
## Direct-kernel booting
### Building kernel
```console
pushd $CLOUDH
git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b ch-6.12.8
cd linux
make ch_defconfig
make -j `nproc`
popd
```
### Booting the guest VM
```console
pushd $CLOUDH
sudo $CLOUDH/cloud-hypervisor/target/debug/cloud-hypervisor \
--kernel $CLOUDH/linux/arch/riscv64/boot/Image \
--disk path=jammy-server-cloudimg-riscv64.raw \
--cmdline "console=hvc0 root=/dev/vda rw" \
--cpus boot=1 \
--memory size=1024M \
--seccomp false \
--log-file boot.log -vv
popd
```
## Known limitations
- Direct kernel boot only
- `64-bit Linux` guest OS only
- For more details, see
[here](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/6978).

70
fuzz/Cargo.lock generated
View File

@@ -425,10 +425,22 @@ dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
name = "getrandom"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
@@ -618,9 +630,9 @@ dependencies = [
[[package]]
name = "mshv-bindings"
version = "0.3.2"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0cb5031f3243a7459b7c13d960d25420980874eebda816db24ce6077e21d43"
checksum = "a9c369385758f81ca937414dc2147737c92032e4fb399669f287abf94d89252d"
dependencies = [
"libc",
"num_enum",
@@ -636,7 +648,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
dependencies = [
"getrandom",
"getrandom 0.2.15",
]
[[package]]
@@ -651,7 +663,7 @@ name = "net_util"
version = "0.1.0"
dependencies = [
"epoll",
"getrandom",
"getrandom 0.3.1",
"libc",
"log",
"net_gen",
@@ -770,20 +782,20 @@ dependencies = [
[[package]]
name = "rand"
version = "0.8.5"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"zerocopy 0.8.14",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core",
@@ -791,11 +803,11 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.6.4"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom",
"getrandom 0.3.1",
]
[[package]]
@@ -834,9 +846,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "seccompiler"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345a3e4dddf721a478089d4697b83c6c0a8f5bf16086f6c13397e4534eb6e2e5"
checksum = "a4ae55de56877481d112a559bbc12667635fdaf5e005712fd4e2b2fa50ffc884"
dependencies = [
"libc",
]
@@ -1052,20 +1064,20 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.10.0"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
dependencies = [
"getrandom",
"getrandom 0.3.1",
"rand",
"uuid-macro-internal",
]
[[package]]
name = "uuid-macro-internal"
version = "1.10.0"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee1cd046f83ea2c4e920d6ee9f7c3537ef928d75dce5d84a87c2c5d6b3999a3a"
checksum = "9521621447c21497fac206ffe6e9f642f977c4f82eeba9201055f64884d9cb01"
dependencies = [
"proc-macro2",
"quote",
@@ -1303,6 +1315,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.93"
@@ -1462,6 +1483,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "zerocopy"
version = "0.7.35"

View File

@@ -27,7 +27,7 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch
mshv-bindings = "0.3.2"
net_util = { path = "../net_util" }
once_cell = "1.19.0"
seccompiler = "0.4.0"
seccompiler = "0.5.0"
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.14.0"
vm-device = { path = "../vm-device" }

View File

@@ -18,8 +18,8 @@ arc-swap = "1.7.1"
byteorder = "1.5.0"
cfg-if = "1.0.0"
concat-idents = "1.1.5"
igvm = { version = "0.3.3", optional = true }
igvm_defs = { version = "0.3.1", optional = true }
igvm = { workspace = true, optional = true }
igvm_defs = { workspace = true, optional = true }
kvm-bindings = { workspace = true, optional = true, features = ["serde"] }
kvm-ioctls = { workspace = true, optional = true }
libc = "0.2.167"

View File

@@ -10,18 +10,21 @@
//
//
#[cfg(target_arch = "aarch64")]
use std::sync::Arc;
use thiserror::Error;
#[cfg(not(target_arch = "riscv64"))]
use vm_memory::GuestAddress;
#[cfg(target_arch = "aarch64")]
use crate::aarch64::{RegList, VcpuInit};
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters};
#[cfg(feature = "tdx")]
use crate::kvm::{TdxExitDetails, TdxExitStatus};
#[cfg(target_arch = "riscv64")]
use crate::riscv64::RegList;
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use crate::RegList;
#[cfg(target_arch = "aarch64")]
use crate::VcpuInit;
use crate::{CpuState, MpState, StandardRegisters};
#[cfg(target_arch = "x86_64")]
@@ -449,7 +452,26 @@ pub trait Vcpu: Send + Sync {
#[cfg(target_arch = "aarch64")]
fn vcpu_finalize(&self, feature: i32) -> Result<()>;
///
/// Gets the features that have been finalized for a given CPU.
///
#[cfg(target_arch = "aarch64")]
fn vcpu_get_finalized_features(&self) -> i32;
///
/// Sets processor features for a given CPU.
///
#[cfg(target_arch = "aarch64")]
fn vcpu_set_processor_features(
&self,
vm: &Arc<dyn crate::Vm>,
kvi: &mut VcpuInit,
id: u8,
) -> Result<()>;
///
/// Returns VcpuInit with default value set
///
#[cfg(target_arch = "aarch64")]
fn create_vcpu_init(&self) -> VcpuInit;
///
/// Gets a list of the guest registers that are supported for the
/// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.

View File

@@ -7,11 +7,11 @@ use kvm_ioctls::DeviceFd;
use crate::arch::aarch64::gic::{Error, Result};
use crate::device::HypervisorDeviceError;
use crate::kvm::kvm_bindings::{
kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG,
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK,
KVM_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_SIZE_U64,
kvm_device_attr, kvm_one_reg, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, KVM_REG_ARM64,
KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT,
KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_SIZE_U64,
};
use crate::kvm::{Register, VcpuKvmState};
use crate::kvm::VcpuKvmState;
use crate::CpuState;
// Relevant redistributor registers that we want to save/restore.
@@ -213,7 +213,7 @@ pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec<u64> {
let state: VcpuKvmState = state.clone().into();
let last = (index == vcpu_states.len() - 1) as u64;
// state.sys_regs is a big collection of system registers, including MIPDR_EL1
let mpidr: Vec<Register> = state
let mpidr: Vec<kvm_one_reg> = state
.sys_regs
.into_iter()
.filter(|reg| reg.id == KVM_ARM64_SYSREG_MPIDR_EL1)

View File

@@ -14,7 +14,6 @@ use kvm_bindings::{
kvm_mp_state, kvm_one_reg, kvm_regs, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_CORE,
KVM_REG_SIZE_MASK, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
};
pub use kvm_bindings::{kvm_one_reg as Register, kvm_vcpu_init as VcpuInit, RegList};
pub use kvm_ioctls::{Cap, Kvm};
use serde::{Deserialize, Serialize};

View File

@@ -30,8 +30,7 @@ use vmm_sys_util::eventfd::EventFd;
use crate::aarch64::gic::KvmGicV3Its;
#[cfg(target_arch = "aarch64")]
pub use crate::aarch64::{
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuInit,
VcpuKvmState,
check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuKvmState,
};
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
@@ -53,15 +52,11 @@ use crate::{offset_of, riscv64_reg_id};
// x86_64 dependencies
#[cfg(target_arch = "x86_64")]
pub mod x86_64;
#[cfg(target_arch = "aarch64")]
use aarch64::{RegList, Register};
#[cfg(target_arch = "x86_64")]
use kvm_bindings::{
kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP,
KVM_GUESTDBG_USE_HW_BP,
};
#[cfg(target_arch = "riscv64")]
use riscv64::{RegList, Register};
#[cfg(target_arch = "x86_64")]
use x86_64::check_required_kvm_extensions;
#[cfg(target_arch = "x86_64")]
@@ -116,6 +111,9 @@ use vfio_ioctls::VfioDeviceFd;
use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_ioc_nr, ioctl_iowr_nr};
pub use {kvm_bindings, kvm_ioctls};
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use crate::RegList;
#[cfg(target_arch = "x86_64")]
const KVM_CAP_SGX_ATTRIBUTE: u32 = 196;
@@ -353,6 +351,61 @@ impl From<ClockData> for kvm_clock_data {
}
}
impl From<kvm_bindings::kvm_one_reg> for crate::Register {
fn from(s: kvm_bindings::kvm_one_reg) -> Self {
crate::Register::Kvm(s)
}
}
impl From<crate::Register> for kvm_bindings::kvm_one_reg {
fn from(e: crate::Register) -> Self {
match e {
crate::Register::Kvm(e) => e,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => panic!("Register is not valid"),
}
}
}
#[cfg(target_arch = "aarch64")]
impl From<kvm_bindings::kvm_vcpu_init> for crate::VcpuInit {
fn from(s: kvm_bindings::kvm_vcpu_init) -> Self {
crate::VcpuInit::Kvm(s)
}
}
#[cfg(target_arch = "aarch64")]
impl From<crate::VcpuInit> for kvm_bindings::kvm_vcpu_init {
fn from(e: crate::VcpuInit) -> Self {
match e {
crate::VcpuInit::Kvm(e) => e,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => panic!("VcpuInit is not valid"),
}
}
}
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
impl From<kvm_bindings::RegList> for crate::RegList {
fn from(s: kvm_bindings::RegList) -> Self {
crate::RegList::Kvm(s)
}
}
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
impl From<crate::RegList> for kvm_bindings::RegList {
fn from(e: crate::RegList) -> Self {
match e {
crate::RegList::Kvm(e) => e,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => panic!("RegList is not valid"),
}
}
}
#[cfg(not(target_arch = "riscv64"))]
impl From<kvm_bindings::kvm_regs> for crate::StandardRegisters {
fn from(s: kvm_bindings::kvm_regs) -> Self {
@@ -754,10 +807,13 @@ impl vm::Vm for KvmVm {
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
///
#[cfg(target_arch = "aarch64")]
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
fn get_preferred_target(&self, kvi: &mut crate::VcpuInit) -> vm::Result<()> {
let mut kvm_kvi: kvm_bindings::kvm_vcpu_init = (*kvi).into();
self.fd
.get_preferred_target(kvi)
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))
.get_preferred_target(&mut kvm_kvi)
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))?;
*kvi = kvm_kvi.into();
Ok(())
}
#[cfg(target_arch = "x86_64")]
@@ -1437,302 +1493,64 @@ impl cpu::Vcpu for KvmVcpu {
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
let mut state = kvm_riscv_core::default();
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, pc);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.pc = u64::from_le_bytes(bytes);
/// Macro used to extract RISC-V register data from KVM Vcpu according
/// to `$reg_name` provided to `state`.
macro_rules! riscv64_get_one_reg_from_vcpu {
(mode) => {
let off = offset_of!(kvm_riscv_core, mode);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.mode = u64::from_le_bytes(bytes);
};
($reg_name:ident) => {
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, $reg_name);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.$reg_name = u64::from_le_bytes(bytes);
};
}
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, ra);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.ra = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, sp);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.sp = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, gp);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.gp = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, tp);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.tp = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t0);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t0 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t1);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t1 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t2);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t2 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s0);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s0 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s1);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s1 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a0);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a0 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a1);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a1 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a2);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a2 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a3);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a3 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a4);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a4 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a5);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a5 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a6);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a6 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a7);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.a7 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s2);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s2 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s3);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s3 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s4);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s4 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s5);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s5 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s6);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s6 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s7);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s7 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s8);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s8 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s9);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s9 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s10);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s10 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s11);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.s11 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t3);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t3 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t4);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t4 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t5);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t5 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t6);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.regs.t6 = u64::from_le_bytes(bytes);
let off = offset_of!(kvm_riscv_core, mode);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(riscv64_reg_id!(KVM_REG_RISCV_CORE, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetRiscvCoreRegister(e.into()))?;
state.mode = u64::from_le_bytes(bytes);
riscv64_get_one_reg_from_vcpu!(pc);
riscv64_get_one_reg_from_vcpu!(ra);
riscv64_get_one_reg_from_vcpu!(sp);
riscv64_get_one_reg_from_vcpu!(gp);
riscv64_get_one_reg_from_vcpu!(tp);
riscv64_get_one_reg_from_vcpu!(t0);
riscv64_get_one_reg_from_vcpu!(t1);
riscv64_get_one_reg_from_vcpu!(t2);
riscv64_get_one_reg_from_vcpu!(s0);
riscv64_get_one_reg_from_vcpu!(s1);
riscv64_get_one_reg_from_vcpu!(a0);
riscv64_get_one_reg_from_vcpu!(a1);
riscv64_get_one_reg_from_vcpu!(a2);
riscv64_get_one_reg_from_vcpu!(a3);
riscv64_get_one_reg_from_vcpu!(a4);
riscv64_get_one_reg_from_vcpu!(a5);
riscv64_get_one_reg_from_vcpu!(a6);
riscv64_get_one_reg_from_vcpu!(a7);
riscv64_get_one_reg_from_vcpu!(s2);
riscv64_get_one_reg_from_vcpu!(s3);
riscv64_get_one_reg_from_vcpu!(s4);
riscv64_get_one_reg_from_vcpu!(s5);
riscv64_get_one_reg_from_vcpu!(s6);
riscv64_get_one_reg_from_vcpu!(s7);
riscv64_get_one_reg_from_vcpu!(s8);
riscv64_get_one_reg_from_vcpu!(s9);
riscv64_get_one_reg_from_vcpu!(s10);
riscv64_get_one_reg_from_vcpu!(s11);
riscv64_get_one_reg_from_vcpu!(t3);
riscv64_get_one_reg_from_vcpu!(t4);
riscv64_get_one_reg_from_vcpu!(t5);
riscv64_get_one_reg_from_vcpu!(t6);
riscv64_get_one_reg_from_vcpu!(mode);
Ok(state.into())
}
@@ -1882,335 +1700,66 @@ impl cpu::Vcpu for KvmVcpu {
// for some additional info on registers.
let kvm_regs_state: kvm_riscv_core = (*state).into();
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, pc);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.pc.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
/// Macro used to set value of specific RISC-V `$reg_name` stored in
/// `state` to KVM Vcpu.
macro_rules! riscv64_set_one_reg_to_vcpu {
(mode) => {
let off = offset_of!(kvm_riscv_core, mode);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.mode.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
};
($reg_name:ident) => {
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, $reg_name);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.$reg_name.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
};
}
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, ra);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.ra.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, sp);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.sp.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, gp);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.gp.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, tp);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.tp.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t0);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t0.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t1);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t1.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t2);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t2.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s0);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s0.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s1);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s1.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a0);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a0.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a1);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a1.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a2);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a2.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a3);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a3.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a4);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a4.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a5);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a5.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a6);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a6.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, a7);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.a7.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s2);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s2.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s3);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s3.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s4);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s4.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s5);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s5.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s6);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s6.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s7);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s7.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s8);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s8.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s9);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s9.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s10);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s10.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, s11);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.s11.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t3);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t3.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t4);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t4.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t5);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t5.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, regs, user_regs_struct, t6);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.regs.t6.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
let off = offset_of!(kvm_riscv_core, mode);
self.fd
.lock()
.unwrap()
.set_one_reg(
riscv64_reg_id!(KVM_REG_RISCV_CORE, off),
&kvm_regs_state.mode.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?;
riscv64_set_one_reg_to_vcpu!(pc);
riscv64_set_one_reg_to_vcpu!(ra);
riscv64_set_one_reg_to_vcpu!(sp);
riscv64_set_one_reg_to_vcpu!(gp);
riscv64_set_one_reg_to_vcpu!(tp);
riscv64_set_one_reg_to_vcpu!(t0);
riscv64_set_one_reg_to_vcpu!(t1);
riscv64_set_one_reg_to_vcpu!(t2);
riscv64_set_one_reg_to_vcpu!(s0);
riscv64_set_one_reg_to_vcpu!(s1);
riscv64_set_one_reg_to_vcpu!(a0);
riscv64_set_one_reg_to_vcpu!(a1);
riscv64_set_one_reg_to_vcpu!(a2);
riscv64_set_one_reg_to_vcpu!(a3);
riscv64_set_one_reg_to_vcpu!(a4);
riscv64_set_one_reg_to_vcpu!(a5);
riscv64_set_one_reg_to_vcpu!(a6);
riscv64_set_one_reg_to_vcpu!(a7);
riscv64_set_one_reg_to_vcpu!(s2);
riscv64_set_one_reg_to_vcpu!(s3);
riscv64_set_one_reg_to_vcpu!(s4);
riscv64_set_one_reg_to_vcpu!(s5);
riscv64_set_one_reg_to_vcpu!(s6);
riscv64_set_one_reg_to_vcpu!(s7);
riscv64_set_one_reg_to_vcpu!(s8);
riscv64_set_one_reg_to_vcpu!(s9);
riscv64_set_one_reg_to_vcpu!(s10);
riscv64_set_one_reg_to_vcpu!(s11);
riscv64_set_one_reg_to_vcpu!(t3);
riscv64_set_one_reg_to_vcpu!(t4);
riscv64_set_one_reg_to_vcpu!(t5);
riscv64_set_one_reg_to_vcpu!(t6);
riscv64_set_one_reg_to_vcpu!(mode);
Ok(())
}
@@ -2602,11 +2151,70 @@ impl cpu::Vcpu for KvmVcpu {
}
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
fn vcpu_get_finalized_features(&self) -> i32 {
kvm_bindings::KVM_ARM_VCPU_SVE as i32
}
#[cfg(target_arch = "aarch64")]
fn vcpu_set_processor_features(
&self,
vm: &Arc<dyn crate::Vm>,
kvi: &mut crate::VcpuInit,
id: u8,
) -> cpu::Result<()> {
use std::arch::is_aarch64_feature_detected;
#[allow(clippy::nonminimal_bool)]
let sve_supported =
is_aarch64_feature_detected!("sve") || is_aarch64_feature_detected!("sve2");
let mut kvm_kvi: kvm_bindings::kvm_vcpu_init = (*kvi).into();
// We already checked that the capability is supported.
kvm_kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2;
if vm
.as_any()
.downcast_ref::<crate::kvm::KvmVm>()
.unwrap()
.check_extension(Cap::ArmPmuV3)
{
kvm_kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PMU_V3;
}
if sve_supported
&& vm
.as_any()
.downcast_ref::<crate::kvm::KvmVm>()
.unwrap()
.check_extension(Cap::ArmSve)
{
kvm_kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_SVE;
}
// Non-boot cpus are powered off initially.
if id > 0 {
kvm_kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
}
*kvi = kvm_kvi.into();
Ok(())
}
///
/// Return VcpuInit with default value set
///
#[cfg(target_arch = "aarch64")]
fn create_vcpu_init(&self) -> crate::VcpuInit {
kvm_bindings::kvm_vcpu_init::default().into()
}
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &crate::VcpuInit) -> cpu::Result<()> {
let kvm_kvi: kvm_bindings::kvm_vcpu_init = (*kvi).into();
self.fd
.lock()
.unwrap()
.vcpu_init(kvi)
.vcpu_init(&kvm_kvi)
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
}
@@ -2625,11 +2233,14 @@ impl cpu::Vcpu for KvmVcpu {
/// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
///
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
let mut kvm_reg_list: kvm_bindings::RegList = reg_list.clone().into();
self.fd
.lock()
.unwrap()
.get_reg_list(reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
.get_reg_list(&mut kvm_reg_list)
.map_err(|e: kvm_ioctls::Error| cpu::HypervisorCpuError::GetRegList(e.into()))?;
*reg_list = kvm_reg_list.into();
Ok(())
}
///
@@ -2917,8 +2528,8 @@ impl cpu::Vcpu for KvmVcpu {
// Get systerm register
// Call KVM_GET_REG_LIST to get all registers available to the guest.
// For ArmV8 there are around 500 registers.
let mut sys_regs: Vec<Register> = Vec::new();
let mut reg_list = RegList::new(500).unwrap();
let mut sys_regs: Vec<kvm_bindings::kvm_one_reg> = Vec::new();
let mut reg_list = kvm_bindings::RegList::new(500).unwrap();
self.fd
.lock()
.unwrap()
@@ -2970,8 +2581,8 @@ impl cpu::Vcpu for KvmVcpu {
// Get non-core register
// Call KVM_GET_REG_LIST to get all registers available to the guest.
// For RISC-V 64-bit there are around 200 registers.
let mut sys_regs: Vec<Register> = Vec::new();
let mut reg_list = RegList::new(200).unwrap();
let mut sys_regs: Vec<kvm_bindings::kvm_one_reg> = Vec::new();
let mut reg_list = kvm_bindings::RegList::new(200).unwrap();
self.fd
.lock()
.unwrap()

View File

@@ -8,7 +8,6 @@ use kvm_bindings::{
kvm_mp_state, kvm_one_reg, kvm_riscv_core, KVM_REG_RISCV_CORE, KVM_REG_RISCV_TYPE_MASK,
KVM_REG_SIZE_MASK, KVM_REG_SIZE_U64,
};
pub use kvm_bindings::{kvm_one_reg as Register, RegList};
pub use kvm_ioctls::{Cap, Kvm};
use serde::{Deserialize, Serialize};

View File

@@ -163,7 +163,7 @@ pub enum IoEventAddress {
pub enum CpuState {
#[cfg(feature = "kvm")]
Kvm(kvm::VcpuKvmState),
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
#[cfg(feature = "mshv")]
Mshv(mshv::VcpuMshvState),
}
@@ -196,16 +196,35 @@ pub enum IrqRoutingEntry {
Mshv(mshv_bindings::mshv_user_irq_entry),
}
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum VcpuInit {
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
Kvm(kvm_bindings::kvm_vcpu_init),
#[cfg(all(feature = "mshv", target_arch = "aarch64"))]
Mshv(mshv_bindings::MshvVcpuInit),
}
#[derive(Debug, Clone, PartialEq)]
pub enum RegList {
#[cfg(all(feature = "kvm", any(target_arch = "aarch64", target_arch = "riscv64")))]
Kvm(kvm_bindings::RegList),
#[cfg(all(feature = "mshv", target_arch = "aarch64"))]
Mshv(mshv_bindings::MshvRegList),
}
pub enum Register {
#[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_one_reg),
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum StandardRegisters {
#[cfg(all(feature = "kvm", not(target_arch = "riscv64")))]
Kvm(kvm_bindings::kvm_regs),
#[cfg(all(feature = "kvm", target_arch = "riscv64"))]
Kvm(kvm_bindings::kvm_riscv_core),
#[cfg(all(
any(feature = "mshv", feature = "mshv_emulator"),
target_arch = "x86_64"
))]
#[cfg(any(feature = "mshv", feature = "mshv_emulator"))]
Mshv(mshv_bindings::StandardRegisters),
}
@@ -292,6 +311,8 @@ macro_rules! set_aarch64_reg {
match self {
#[cfg(feature = "kvm")]
StandardRegisters::Kvm(s) => s.regs.$reg_name = val,
#[cfg(feature = "mshv")]
StandardRegisters::Mshv(s) => s.$reg_name = val,
}
}
}
@@ -308,6 +329,8 @@ macro_rules! get_aarch64_reg {
match self {
#[cfg(feature = "kvm")]
StandardRegisters::Kvm(s) => s.regs.$reg_name,
#[cfg(feature = "mshv")]
StandardRegisters::Mshv(s) => s.$reg_name,
}
}
}

View File

@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2025, Microsoft Corporation
//
use std::fmt;
///
/// Export generically-named wrappers of mshv_bindings for Unix-based platforms
///
pub use mshv_bindings::StandardRegisters as MshvStandardRegisters;
use serde::{Deserialize, Serialize};
#[derive(Clone, Serialize, Deserialize)]
pub struct VcpuMshvState {
pub regs: MshvStandardRegisters,
}
impl fmt::Display for VcpuMshvState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Standard registers: {:?}", self.regs)
}
}

View File

@@ -12,15 +12,19 @@ use std::sync::{Arc, RwLock};
#[cfg(feature = "sev_snp")]
use arc_swap::ArcSwap;
use mshv_bindings::*;
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
#[cfg(target_arch = "x86_64")]
use mshv_ioctls::{set_registers_64, InterruptRequest};
use mshv_ioctls::{Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
use vfio_ioctls::VfioDeviceFd;
use vm::DataMatch;
#[cfg(feature = "sev_snp")]
use vm_memory::bitmap::AtomicBitmap;
#[cfg(target_arch = "x86_64")]
use crate::arch::emulator::PlatformEmulator;
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::emulator::Emulator;
#[cfg(target_arch = "x86_64")]
use crate::mshv::emulator::MshvEmulatorContext;
use crate::vm::{self, InterruptSourceConfig, VmOps};
use crate::{cpu, hypervisor, vec_with_array_field, HypervisorType};
@@ -29,10 +33,17 @@ mod snp_constants;
// x86_64 dependencies
#[cfg(target_arch = "x86_64")]
pub mod x86_64;
// aarch64 dependencies
#[cfg(target_arch = "aarch64")]
pub mod aarch64;
#[cfg(target_arch = "x86_64")]
use std::fs::File;
use std::os::unix::io::AsRawFd;
#[cfg(target_arch = "aarch64")]
use std::sync::Mutex;
#[cfg(target_arch = "aarch64")]
pub use aarch64::VcpuMshvState;
#[cfg(feature = "sev_snp")]
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
#[cfg(feature = "sev_snp")]
@@ -50,6 +61,8 @@ pub use {
mshv_bindings::mshv_device_attr as DeviceAttr, mshv_ioctls, mshv_ioctls::DeviceFd,
};
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{CpuIdEntry, FpuState, MsrEntry};
#[cfg(target_arch = "x86_64")]
@@ -191,6 +204,44 @@ impl From<IrqRoutingEntry> for mshv_user_irq_entry {
}
}
#[cfg(target_arch = "aarch64")]
impl From<mshv_bindings::MshvRegList> for crate::RegList {
fn from(s: mshv_bindings::MshvRegList) -> Self {
crate::RegList::Mshv(s)
}
}
#[cfg(target_arch = "aarch64")]
impl From<crate::RegList> for mshv_bindings::MshvRegList {
fn from(e: crate::RegList) -> Self {
match e {
crate::RegList::Mshv(e) => e,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => panic!("RegList is not valid"),
}
}
}
#[cfg(target_arch = "aarch64")]
impl From<mshv_bindings::MshvVcpuInit> for crate::VcpuInit {
fn from(s: mshv_bindings::MshvVcpuInit) -> Self {
crate::VcpuInit::Mshv(s)
}
}
#[cfg(target_arch = "aarch64")]
impl From<crate::VcpuInit> for mshv_bindings::MshvVcpuInit {
fn from(e: crate::VcpuInit) -> Self {
match e {
crate::VcpuInit::Mshv(e) => e,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => panic!("VcpuInit is not valid"),
}
}
}
struct MshvDirtyLogSlot {
guest_pfn: u64,
memory_size: u64,
@@ -443,6 +494,23 @@ impl hypervisor::Hypervisor for MshvHypervisor {
fn get_guest_debug_hw_bps(&self) -> usize {
0
}
#[cfg(target_arch = "aarch64")]
///
/// Retrieve AArch64 host maximum IPA size supported by MSHV.
///
fn get_host_ipa_limit(&self) -> i32 {
let host_ipa = self.mshv.get_host_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_PHYSICAL_ADDRESS_WIDTH as u64,
);
match host_ipa {
Ok(ipa) => ipa,
Err(e) => {
panic!("Failed to get host IPA limit: {:?}", e);
}
}
}
}
#[cfg(feature = "sev_snp")]
@@ -1238,25 +1306,50 @@ impl cpu::Vcpu for MshvVcpu {
}
#[cfg(target_arch = "aarch64")]
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
fn get_reg_list(&self, _reg_list: &mut crate::RegList) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
fn vcpu_init(&self, _kvi: &crate::VcpuInit) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
fn set_regs(&self, _regs: &crate::StandardRegisters) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
fn get_regs(&self) -> cpu::Result<crate::StandardRegisters> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn vcpu_finalize(&self, _feature: i32) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn vcpu_get_finalized_features(&self) -> i32 {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn vcpu_set_processor_features(
&self,
_vm: &Arc<dyn crate::Vm>,
_kvi: &mut crate::VcpuInit,
_id: u8,
) -> cpu::Result<()> {
unimplemented!()
}
#[cfg(target_arch = "aarch64")]
fn create_vcpu_init(&self) -> crate::VcpuInit {
unimplemented!();
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to setup the CPUID registers.
@@ -1868,7 +1961,7 @@ impl vm::Vm for MshvVm {
fn create_passthrough_device(&self) -> vm::Result<VfioDeviceFd> {
let mut vfio_dev = mshv_create_device {
type_: mshv_device_type_MSHV_DEV_TYPE_VFIO,
type_: MSHV_DEV_TYPE_VFIO,
fd: 0,
flags: 0,
};
@@ -2095,7 +2188,7 @@ impl vm::Vm for MshvVm {
}
#[cfg(target_arch = "aarch64")]
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
fn get_preferred_target(&self, _kvi: &mut crate::VcpuInit) -> vm::Result<()> {
unimplemented!()
}

View File

@@ -35,12 +35,7 @@ impl MshvEmulatorContext<'_> {
}
}
fn read_memory_flags(
&self,
gva: u64,
data: &mut [u8],
flags: u32,
) -> Result<(), PlatformError> {
fn r(&self, gva: u64, data: &mut [u8], flags: u32) -> Result<(), PlatformError> {
let gpa = self.translate(gva, flags)?;
debug!(
"mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]",
@@ -59,17 +54,38 @@ impl MshvEmulatorContext<'_> {
Ok(())
}
}
/// Platform emulation for Hyper-V
impl PlatformEmulator for MshvEmulatorContext<'_> {
type CpuState = EmulatorCpuState;
fn read_memory_flags(
&self,
gva: u64,
data: &mut [u8],
flags: u32,
) -> Result<(), PlatformError> {
let mut len = data.len() as u64;
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
self.read_memory_flags(gva, data, HV_TRANSLATE_GVA_VALIDATE_READ)
// Compare the page number of the first and last byte. If they are different, this is a
// cross-page access.
let pg1 = gva >> HV_HYP_PAGE_SHIFT;
let pg2 = (gva + len - 1) >> HV_HYP_PAGE_SHIFT;
let cross_page = pg1 != pg2;
if cross_page {
// We only handle one page cross-page access
assert!(pg1 + 1 == pg2);
let n = (gva + len) & HV_HYP_PAGE_MASK as u64;
len -= n;
}
self.r(gva, &mut data[..len as usize], flags)?;
if cross_page {
self.r(gva + len, &mut data[len as usize..], flags)?;
}
Ok(())
}
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
fn w(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
let gpa = self.translate(gva, HV_TRANSLATE_GVA_VALIDATE_WRITE)?;
debug!(
"mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]",
@@ -88,6 +104,40 @@ impl PlatformEmulator for MshvEmulatorContext<'_> {
Ok(())
}
}
/// Platform emulation for Hyper-V
impl PlatformEmulator for MshvEmulatorContext<'_> {
type CpuState = EmulatorCpuState;
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
self.read_memory_flags(gva, data, HV_TRANSLATE_GVA_VALIDATE_READ)
}
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
let mut len = data.len() as u64;
// Compare the page number of the first and last byte. If they are different, this is a
// cross-page access.
let pg1 = gva >> HV_HYP_PAGE_SHIFT;
let pg2 = (gva + len - 1) >> HV_HYP_PAGE_SHIFT;
let cross_page = pg1 != pg2;
if cross_page {
// We only handle one page cross-page access
assert!(pg1 + 1 == pg2);
let n = (gva + len) & HV_HYP_PAGE_MASK as u64;
len -= n;
}
self.w(gva, &data[..len as usize])?;
if cross_page {
self.w(gva + len, &data[len as usize..])?;
}
Ok(())
}
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError> {
if cpu_id != self.vcpu.vp_index as usize {

View File

@@ -22,8 +22,6 @@ use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd;
#[cfg(target_arch = "aarch64")]
use crate::aarch64::VcpuInit;
#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::gic::{Vgic, VgicConfig};
#[cfg(target_arch = "riscv64")]
@@ -351,7 +349,7 @@ pub trait Vm: Send + Sync + Any {
fn remove_user_memory_region(&self, user_memory_region: UserMemoryRegion) -> Result<()>;
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
#[cfg(target_arch = "aarch64")]
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> Result<()>;
fn get_preferred_target(&self, kvi: &mut crate::VcpuInit) -> Result<()>;
/// Enable split Irq capability
#[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> Result<()>;

View File

@@ -6,7 +6,7 @@ version = "0.1.0"
[dependencies]
epoll = "4.3.3"
getrandom = "0.2.15"
getrandom = "0.3.1"
libc = "0.2.167"
log = "0.4.22"
net_gen = { path = "../net_gen" }

View File

@@ -80,7 +80,7 @@ impl MacAddr {
pub fn local_random() -> MacAddr {
// Generate a fully random MAC
let mut random_bytes = [0u8; MAC_ADDR_LEN];
if let Err(e) = getrandom::getrandom(&mut random_bytes) {
if let Err(e) = getrandom::fill(&mut random_bytes) {
error!(
"Error populating MAC address with random data: {}",
e.to_string()

View File

@@ -7,6 +7,7 @@ use std::any::Any;
use std::collections::{BTreeMap, HashMap};
use std::io;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use std::ptr::null_mut;
use std::sync::{Arc, Barrier, Mutex};
@@ -48,10 +49,10 @@ pub(crate) const VFIO_COMMON_ID: &str = "vfio_common";
pub enum VfioPciError {
#[error("Failed to create user memory region: {0}")]
CreateUserMemoryRegion(#[source] HypervisorVmError),
#[error("Failed to DMA map: {0} for device {1}")]
DmaMap(#[source] vfio_ioctls::VfioError, PciBdf),
#[error("Failed to DMA unmap: {0} for device {1}")]
DmaUnmap(#[source] vfio_ioctls::VfioError, PciBdf),
#[error("Failed to DMA map: {0} for device {1} (guest BDF: {2})")]
DmaMap(#[source] vfio_ioctls::VfioError, PathBuf, PciBdf),
#[error("Failed to DMA unmap: {0} for device {1} (guest BDF: {2})")]
DmaUnmap(#[source] vfio_ioctls::VfioError, PathBuf, PciBdf),
#[error("Failed to enable INTx: {0}")]
EnableIntx(#[source] VfioError),
#[error("Failed to enable MSI: {0}")]
@@ -1411,6 +1412,7 @@ pub struct VfioPciDevice {
iommu_attached: bool,
memory_slot_allocator: MemorySlotAllocator,
bdf: PciBdf,
device_path: PathBuf,
}
impl VfioPciDevice {
@@ -1428,6 +1430,7 @@ impl VfioPciDevice {
memory_slot_allocator: MemorySlotAllocator,
snapshot: Option<Snapshot>,
x_nv_gpudirect_clique: Option<u8>,
device_path: PathBuf,
) -> Result<Self, VfioPciError> {
let device = Arc::new(device);
device.reset();
@@ -1453,6 +1456,7 @@ impl VfioPciDevice {
iommu_attached,
memory_slot_allocator,
bdf,
device_path: device_path.clone(),
};
Ok(vfio_pci_device)
@@ -1552,7 +1556,7 @@ impl VfioPciDevice {
/// # Arguments
///
/// * `vm` - The VM object. It is used to set the VFIO MMIO regions
/// as user memory regions.
/// as user memory regions.
/// * `mem_slot` - The closure to return a memory slot.
pub fn map_mmio_regions(&mut self) -> Result<(), VfioPciError> {
let fd = self.device.as_raw_fd();
@@ -1658,7 +1662,9 @@ impl VfioPciDevice {
user_memory_region.size,
user_memory_region.host_addr,
)
.map_err(|e| VfioPciError::DmaMap(e, self.bdf))?;
.map_err(|e| {
VfioPciError::DmaMap(e, self.device_path.clone(), self.bdf)
})?;
}
}
}
@@ -1719,7 +1725,7 @@ impl VfioPciDevice {
if !self.iommu_attached {
self.container
.vfio_dma_map(iova, size, user_addr)
.map_err(|e| VfioPciError::DmaMap(e, self.bdf))?;
.map_err(|e| VfioPciError::DmaMap(e, self.device_path.clone(), self.bdf))?;
}
Ok(())
@@ -1729,7 +1735,7 @@ impl VfioPciDevice {
if !self.iommu_attached {
self.container
.vfio_dma_unmap(iova, size)
.map_err(|e| VfioPciError::DmaUnmap(e, self.bdf))?;
.map_err(|e| VfioPciError::DmaUnmap(e, self.device_path.clone(), self.bdf))?;
}
Ok(())

View File

@@ -7,7 +7,7 @@ version = "0.1.0"
[dependencies]
clap = { version = "4.5.13", features = ["wrap_help"] }
dirs = "5.0.1"
dirs = "6.0.0"
serde = { version = "1.0.208", features = ["derive", "rc"] }
serde_json = "1.0.120"
test_infra = { path = "../test_infra" }

View File

@@ -1,36 +1,42 @@
- [v45.0](#v450)
- [Experimental `riscv64` Architecture Support](#experimental-riscv64-architecture-support)
- [Alphabetically Sorted CLI Options](#alphabetically-sorted-cli-options)
- [Improved Downtime from VM Live Migration](#improved-downtime-from-vm-live-migration)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [v44.0](#v440)
- [Configurable `virtio-iommu` Address Width](#configurable-virtio-iommu-address-width)
- [Notable Performance Improvements](#notable-performance-improvements)
- [New Fuzzers](#new-fuzzers)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [v43.0](#v430)
- [Live Migration over TCP Connections](#live-migration-over-tcp-connections)
- [Notable Performance Improvements](#notable-performance-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-2)
- [v42.0](#v420)
- [SVE/SVE2 Support on AArch64](#svesve2-support-on-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Sponsorships](#sponsorships)
- [Contributors](#contributors-2)
- [Contributors](#contributors-3)
- [v41.0](#v410)
- [Experimental "Pvmemcontrol" Support](#experimental-pvmemcontrol-support)
- [Sandboxing With Landlock Support](#sandboxing-with-landlock-support)
- [Notable Performance Improvements](#notable-performance-improvements-2)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-3)
- [v40.0](#v400)
- [Support for Restoring File Descriptor Backed Network Devices](#support-for-restoring-file-descriptor-backed-network-devices)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-4)
- [v40.0](#v400)
- [Support for Restoring File Descriptor Backed Network Devices](#support-for-restoring-file-descriptor-backed-network-devices)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [v39.0](#v390)
- [Variable Sizing of PCI Apertures for Segments](#variable-sizing-of-pci-apertures-for-segments)
- [Direct Booting with bzImages](#direct-booting-with-bzimages)
- [Support for NVIDIA GPUDirect P2P Support](#support-for-nvidia-gpudirect-p2p-support)
- [Guest NMI Injection Support](#guest-nmi-injection-support)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [v38.0](#v380)
- [Group Rate Limiter on Block Devices](#group-rate-limiter-on-block-devices)
- [CPU Pinning Support for Block Device Worker Thread](#cpu-pinning-support-for-block-device-worker-thread)
@@ -38,16 +44,16 @@
- [New 'debug-console' Device](#new-debug-console-device)
- [Improved VFIO Device Support](#improved-vfio-device-support)
- [Extended CPU Affinity Support](#extended-cpu-affinity-support)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [v37.0](#v370)
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [Multiple PCI segments Support for 32-bit VFIO devices](#multiple-pci-segments-support-for-32-bit-vfio-devices)
- [Configurable Named TAP Devices](#configurable-named-tap-devices)
- [TTY Output from Both Serial Device and Virtio Console](#tty-output-from-both-serial-device-and-virtio-console)
- [Faster VM Restoration from Snapshots](#faster-vm-restoration-from-snapshots)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [v36.0](#v360)
- [Command Line Changes](#command-line-changes)
- [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli)
@@ -56,31 +62,31 @@
- [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port)
- [AIO Backend for Block Devices](#aio-backend-for-block-devices)
- [Documentation Improvements](#documentation-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [v35.0](#v350)
- [`virtio-vsock` Support for Linux Guest Kernel v6.3+](#virtio-vsock-support-for-linux-guest-kernel-v63)
- [User Specified Serial Number for `virtio-block`](#user-specified-serial-number-for-virtio-block)
- [vCPU TSC Frequency Included in Migration State](#vcpu-tsc-frequency-included-in-migration-state)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Contributors](#contributors-10)
- [v34.0](#v340)
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Contributors](#contributors-10)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Contributors](#contributors-11)
- [v33.0](#v330)
- [D-Bus based API](#d-bus-based-api)
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Contributors](#contributors-11)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Contributors](#contributors-12)
- [v32.0](#v320)
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
- [API Changes](#api-changes)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Contributors](#contributors-12)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Contributors](#contributors-13)
- [v31.1](#v311)
- [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
@@ -88,15 +94,15 @@
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
- [Documentation Improvements](#documentation-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Contributors](#contributors-13)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Contributors](#contributors-14)
- [v30.0](#v300)
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
- [Heap Profiling Support](#heap-profiling-support)
- [Documentation Improvements](#documentation-improvements-2)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Contributors](#contributors-14)
- [Notable Bug Fixes](#notable-bug-fixes-15)
- [Contributors](#contributors-15)
- [v28.2](#v282)
- [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
@@ -106,10 +112,10 @@
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
- [TCP Offload Control](#tcp-offload-control)
- [Notable Bug Fixes](#notable-bug-fixes-15)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Removals](#removals)
- [Deprecations](#deprecations)
- [Contributors](#contributors-15)
- [Contributors](#contributors-16)
- [v28.1](#v281)
- [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder)
@@ -117,9 +123,9 @@
- [Virtualised TPM Support](#virtualised-tpm-support)
- [Transparent Huge Page Support](#transparent-huge-page-support)
- [README Quick Start Improved](#readme-quick-start-improved)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Notable Bug Fixes](#notable-bug-fixes-17)
- [Removals](#removals-1)
- [Contributors](#contributors-16)
- [Contributors](#contributors-17)
- [v27.0](#v270)
- [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages)
@@ -128,41 +134,41 @@
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
- [GDB Support for AArch64](#gdb-support-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-17)
- [Notable Bug Fixes](#notable-bug-fixes-18)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-17)
- [Contributors](#contributors-18)
- [v26.0](#v260)
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
- [Notable Bug Fixes](#notable-bug-fixes-18)
- [Notable Bug Fixes](#notable-bug-fixes-19)
- [Deprecations](#deprecations-2)
- [Removals](#removals-2)
- [Contributors](#contributors-18)
- [Contributors](#contributors-19)
- [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-19)
- [Notable Bug Fixes](#notable-bug-fixes-20)
- [Removals](#removals-3)
- [Contributors](#contributors-19)
- [Contributors](#contributors-20)
- [v24.0](#v240)
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
- [Sparse Mmap support](#sparse-mmap-support)
- [Expose Platform Serial Number](#expose-platform-serial-number)
- [Notable Bug Fixes](#notable-bug-fixes-20)
- [Notable Bug Fixes](#notable-bug-fixes-21)
- [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website)
- [Contributors](#contributors-20)
- [Contributors](#contributors-21)
- [v23.1](#v231)
- [v23.0](#v230)
- [vDPA Support](#vdpa-support)
- [Updated OS Support list](#updated-os-support-list)
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
- [`AMX` Support](#amx-support)
- [Notable Bug Fixes](#notable-bug-fixes-21)
- [Notable Bug Fixes](#notable-bug-fixes-22)
- [Deprecations](#deprecations-4)
- [Contributors](#contributors-21)
- [Contributors](#contributors-22)
- [v22.1](#v221)
- [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support)
@@ -173,13 +179,13 @@
- [PMU Support for AArch64](#pmu-support-for-aarch64)
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
- [Notable Bug Fixes](#notable-bug-fixes-22)
- [Contributors](#contributors-22)
- [Notable Bug Fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-23)
- [v21.0](#v210)
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
- [Notable Bug fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-23)
- [Notable Bug fixes](#notable-bug-fixes-24)
- [Contributors](#contributors-24)
- [v20.2](#v202)
- [v20.1](#v201)
- [v20.0](#v200)
@@ -188,8 +194,8 @@
- [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code)
- [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-24)
- [Contributors](#contributors-24)
- [Notable bug fixes](#notable-bug-fixes-25)
- [Contributors](#contributors-25)
- [v19.0](#v190)
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
- [PCI boot time optimisations](#pci-boot-time-optimisations)
@@ -197,8 +203,8 @@
- [Live migration enhancements](#live-migration-enhancements)
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
- [Notable bug fixes](#notable-bug-fixes-25)
- [Contributors](#contributors-25)
- [Notable bug fixes](#notable-bug-fixes-26)
- [Contributors](#contributors-26)
- [v18.0](#v180)
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
@@ -208,23 +214,23 @@
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
- [Power button support on AArch64](#power-button-support-on-aarch64)
- [Notable bug fixes](#notable-bug-fixes-26)
- [Contributors](#contributors-26)
- [Notable bug fixes](#notable-bug-fixes-27)
- [Contributors](#contributors-27)
- [v17.0](#v170)
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
- [Improved SGX support](#improved-sgx-support)
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
- [Notable bug fixes](#notable-bug-fixes-27)
- [Contributors](#contributors-27)
- [Notable bug fixes](#notable-bug-fixes-28)
- [Contributors](#contributors-28)
- [v16.0](#v160)
- [Improved live migration support](#improved-live-migration-support)
- [Improved `vhost-user` support](#improved-vhost-user-support)
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
- [Notable bug fixes](#notable-bug-fixes-28)
- [Notable bug fixes](#notable-bug-fixes-29)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors-28)
- [Contributors](#contributors-29)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@@ -232,7 +238,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5)
- [Contributors](#contributors-29)
- [Contributors](#contributors-30)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@@ -242,7 +248,7 @@
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
- [Block device rate limiting](#block-device-rate-limiting)
- [Deprecations](#deprecations-6)
- [Contributors](#contributors-30)
- [Contributors](#contributors-31)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@@ -250,13 +256,13 @@
- [VHD disk image support](#vhd-disk-image-support)
- [Improved Virtio device threading](#improved-virtio-device-threading)
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
- [Contributors](#contributors-31)
- [Contributors](#contributors-32)
- [v0.12.0](#v0120)
- [ARM64 enhancements](#arm64-enhancements)
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
- [Enhanced "info" API](#enhanced-info-api)
- [Contributors](#contributors-32)
- [Contributors](#contributors-33)
- [v0.11.0](#v0110)
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
- [Windows Guest Support](#windows-guest-support)
@@ -268,15 +274,15 @@
- [Default Log Level Changed](#default-log-level-changed)
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
- [Notable Bug Fixes](#notable-bug-fixes-29)
- [Contributors](#contributors-33)
- [Notable Bug Fixes](#notable-bug-fixes-30)
- [Contributors](#contributors-34)
- [v0.10.0](#v0100)
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
- [Memory Zones](#memory-zones)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
- [Notable Bug Fixes](#notable-bug-fixes-30)
- [Contributors](#contributors-34)
- [Notable Bug Fixes](#notable-bug-fixes-31)
- [Contributors](#contributors-35)
- [v0.9.0](#v090)
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
- [Block and Network Device Statistics](#block-and-network-device-statistics)
@@ -289,17 +295,17 @@
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
- [Intel SGX Support](#intel-sgx-support)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-31)
- [Contributors](#contributors-35)
- [Notable Bug Fixes](#notable-bug-fixes-32)
- [Contributors](#contributors-36)
- [v0.8.0](#v080)
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
- [Experimental ARM64 Support](#experimental-arm64-support)
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-32)
- [Notable Bug Fixes](#notable-bug-fixes-33)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-36)
- [Contributors](#contributors-37)
- [v0.7.0](#v070)
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
- [Alternative `libc` Support](#alternative-libc-support)
@@ -309,14 +315,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-37)
- [Contributors](#contributors-38)
- [v0.6.0](#v060)
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
- [Command Line Interface](#command-line-interface)
- [PVH Boot](#pvh-boot)
- [Contributors](#contributors-38)
- [Contributors](#contributors-39)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -324,7 +330,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-39)
- [Contributors](#contributors-40)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -333,7 +339,7 @@
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
- [PCI BAR reprogramming](#pci-bar-reprogramming)
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
- [Contributors](#contributors-40)
- [Contributors](#contributors-41)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@@ -360,11 +366,53 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# v45.0
This release has been tracked in [v45.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v44.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Experimental `riscv64` Architecture Support
Cloud Hypervisor now has experimental `riscv64` architecture
support. Details can be found from the [riscv
documentation](docs/riscv.md).
### Alphabetically Sorted CLI Options
To improve the readability of CLI options, the output of the `--help`
now is alphabetically sorted. (#6988)
### Improved Downtime of VM Live Migration
The downtime of VM live migration is reduced via delaying some of the
tearing down process of the source VM after the destination VM is up and
running. (#6987)
### Notable Bug Fixes
* Fix seccomp filters related to http-api thread (#6967)
* Handle cross-page access in the emulator for mshv (#6968)
### Contributors
Many thanks to everyone who has contributed to our release:
* Anatol Belski <anbelski@linux.microsoft.com>
* Andrew Consroe <aconz2@gmail.com>
* Bo Chen <bchen@crusoe.ai>
* Jinank Jain <jinankjain@microsoft.com>
* Jinrong Liang <cloudliang@tencent.com>
* Philipp Schuster <philipp.schuster@cyberus-technology.de>
* Ruoqing He <heruoqing@iscas.ac.cn>
* Stefan Kober <stefan.kober@cyberus-technology.de>
* Wei Liu <liuwe@microsoft.com>
# v44.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v44.0. The following user visible changes have been made:
This release has been tracked in [v44.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v44.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Configurable `virtio-iommu` Address Width
@@ -405,9 +453,9 @@ Many thanks to everyone who has contributed to our release:
# v43.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v43.0. The following user visible changes have been made:
This release has been tracked in [v43.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v43.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Live Migration over TCP Connections
@@ -447,9 +495,9 @@ Many thanks to everyone who has contributed to our release:
# v42.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v42.0. The following user visible changes have been made:
This release has been tracked in [v42.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v42.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### SVE/SVE2 Support on AArch64
@@ -496,9 +544,9 @@ Many thanks to everyone who has contributed to our release:
# v41.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v41.0. The following user visible changes have been made:
This release has been tracked in [v41.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v41.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Experimental "Pvmemcontrol" Support
@@ -555,9 +603,9 @@ Many thanks to everyone who has contributed to our release:
# v40.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v40.0. The following user visible changes have been made:
This release has been tracked in [v40.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v40.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Support for Restoring File Descriptor Backed Network Devices
@@ -606,9 +654,9 @@ Many thanks to everyone who has contributed to our release:
# v39.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v39.0. The following user visible changes have been made:
This release has been tracked in [v39.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v39.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Variable Sizing of PCI Apertures for Segments
@@ -677,9 +725,9 @@ Many thanks to everyone who has contributed to our release:
# v38.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v38.0. The following user visible changes have been made:
This release has been tracked in [v38.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v38.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Group Rate Limiter on Block Devices
@@ -747,9 +795,9 @@ Many thanks to everyone who has contributed to our release:
# v37.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v37.0. The following user visible changes have been made:
This release has been tracked in [v37.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v37.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Long Term Support (LTS) Release
@@ -809,9 +857,9 @@ Many thanks to everyone who has contributed to our release:
# v36.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v36.0. The following user visible changes have been made:
This release has been tracked in [v36.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v36.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Command Line Changes
@@ -884,9 +932,9 @@ Many thanks to everyone who has contributed to our release:
# v35.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v35.0. The following user visible changes have been made:
This release has been tracked in [v35.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v35.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### `virtio-vsock` Support for Linux Guest Kernel v6.3+
@@ -937,9 +985,9 @@ Many thanks to everyone who has contributed to our release:
# v34.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v34.0. The following user visible changes have been made:
This release has been tracked in [v34.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v34.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Paravirtualised Panic Device Support
@@ -997,9 +1045,9 @@ Many thanks to everyone who has contributed to our release:
# v33.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v33.0. The following user visible changes have been made:
This release has been tracked in [v33.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v33.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### D-Bus based API
@@ -1041,9 +1089,9 @@ Many thanks to everyone who has contributed to our release:
# v32.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v32.0. The following user visible changes have been made:
This release has been tracked in [v32.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v32.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Increased PCI Segment Limit
@@ -1094,9 +1142,9 @@ This is a bug fix release. The following issues have been addressed:
# v31.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v31.0. The following user visible changes have been made:
This release has been tracked in [v31.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v31.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Update to Latest `acpi_tables`
@@ -1160,9 +1208,9 @@ Many thanks to everyone who has contributed to our release:
# v30.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v30.0. The following user visible changes have been made:
This release has been tracked in [v30.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v30.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Command Line Changes for Reduced Binary Size
@@ -1190,7 +1238,7 @@ heap profiling using `dhat` gated by the `dhat-heap` feature.
The documentation on Intel TDX is expanded with details of the building
and using [TD-Shim](https://github.com/confidential-containers/td-shim),
references to [TDX Tools](https://github.com/intel/tdx-tools), and
references to [TDX Linux](https://github.com/intel/tdx-linux), and
version information of guest/host kernel/TDVF/TDShim being tested. Also,
a new 'heap profiling' documentation is added with improvements on the
existing 'profiling' documentation.
@@ -1233,9 +1281,9 @@ This is a bug fix release. The following issues have been addressed:
# v29.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v29.0. The following user visible changes have been made:
This release has been tracked in [v29.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v29.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Release Binary Supports Both MSHV and KVM
@@ -1330,9 +1378,9 @@ addresses an infinite loop issue ([details](https://github.com/rust-vmm/linux-lo
# v28.0
This release has been tracked in our new [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v28.0.
This release has been tracked in [v28.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v28.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Community Engagement (Reminder)
@@ -1406,9 +1454,9 @@ Many thanks to everyone who has contributed to our release:
# v27.0
This release has been tracked in our new [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v27.0.
This release has been tracked in [v27.0
group](https://github.com/orgs/cloud-hypervisor/projects/6/views/4?filterQuery=release%3A%22Release+v27.0%22)
of our [roadmap project](https://github.com/orgs/cloud-hypervisor/projects/6/).
### Community Engagement
@@ -1497,9 +1545,6 @@ Many thanks to everyone who has contributed to our release:
# v26.0
This release has been tracked through the [v26.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/30).
### SMBIOS Improvements via `--platform`
`--platform` and the appropriate API structure has gained support for supplying
@@ -1563,9 +1608,6 @@ Many thanks to everyone who has contributed to our release:
# v25.0
This release has been tracked through the [v25.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/29).
### `ch-remote` Improvements
The `ch-remote` command has gained support for creating the VM from a JSON
@@ -1609,9 +1651,6 @@ Many thanks to everyone who has contributed to our release:
# v24.0
This release has been tracked through the [v24.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/28).
### Bypass Mode for `virtio-iommu`
`virtio-iommu` specification describes how a device can be attached by default
@@ -1697,9 +1736,6 @@ This is a bug fix release. The following issues have been addressed:
# v23.0
This release has been tracked through the [v23.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/27).
### vDPA Support
A vDPA device has a datapath that complies with the virtio specification but
@@ -1768,9 +1804,6 @@ This is a bug fix release. The following issues have been addressed:
# v22.0
This release has been tracked through the [v22.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/25).
### GDB Debug Stub Support
Cloud Hypervisor can now be used as debug target with GDB. This is controlled
@@ -1851,9 +1884,6 @@ Many thanks to everyone who has contributed to our release:
# v21.0
This release has been tracked through the [v21.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/24).
### Efficient Local Live Migration (for Live Upgrade)
In order to support fast live upgrade of the VMM an optimised path has been
@@ -1916,9 +1946,6 @@ This is a bug fix release. The following issues have been addressed:
# v20.0
This release has been tracked through the [v20.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/23).
### Multiple PCI segments support
Cloud Hypervisor is no longer limited to 31 PCI devices. For both `x86_64` and
@@ -1974,9 +2001,6 @@ Many thanks to everyone who has contributed to our release:
# v19.0
This release has been tracked through the [v19.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/22).
### Improved PTY handling for serial and `virtio-console`
The PTY support for serial has been enhanced with improved buffering when the
@@ -2037,9 +2061,6 @@ Many thanks to everyone who has contributed to our release:
# v18.0
This release has been tracked through the [v18.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/21).
### Experimental User Device (`vfio-user`) support
Experimental support for running PCI devices in userspace via `vfio-user`
@@ -2110,9 +2131,6 @@ Many thanks to everyone who has contributed to our release:
# v17.0
This release has been tracked through the [v17.0
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/20).
### ARM64 NUMA support using ACPI
The support for ACPI on ARM64 has been enhanced to include support for
@@ -2168,8 +2186,6 @@ Many thanks to everyone who has contributed to our release:
# v16.0
This release has been tracked through the [v16.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/19).
### Improved live migration support
The live migration support inside Cloud Hypervisor has been improved with the addition of the tracking of dirty pages written by the VMM to complement the tracking of dirty pages made by the guest itself. Further the internal state of the VMM now is versioned which allows the safe migration of VMs from one version of the VMM to a newer one. However further testing is required so this should be done with care. See the [live migration documentation](docs/live_migration.md) for more details.
@@ -2217,8 +2233,6 @@ Many thanks to everyone who has contributed to our release including some new fa
# v15.0
This release has been tracked through the [v15.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/18).
Highlights for `cloud-hypervisor` version v15.0 include:
### Version numbering and stability guarantees
@@ -2308,8 +2322,6 @@ in this release:
# v0.14.0
This release has been tracked through the [0.14.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/17).
Highlights for `cloud-hypervisor` version 0.14.0 include:
### Structured event monitoring
@@ -2380,8 +2392,6 @@ some new faces.
# v0.13.0
This release has been tracked through the [0.13.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/16).
Highlights for `cloud-hypervisor` version 0.13.0 include:
### Wider VFIO device support
@@ -2442,8 +2452,6 @@ some new faces.
# v0.12.0
This release has been tracked through the [0.12.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/15).
Highlights for `cloud-hypervisor` version 0.12.0 include:
### ARM64 enhancements
@@ -2483,8 +2491,6 @@ Many thanks to everyone who has contributed to our 0.12.0 release:
# v0.11.0
This release has been tracked through the [0.11.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/14).
Highlights for `cloud-hypervisor` version 0.11.0 include:
### `io_uring` support by default for `virtio-block`
@@ -2533,7 +2539,7 @@ resources.
The default logging level was changed to include warnings which should make it
easier to see potential issues. New [logging
documentation](docs/logging) was also added.
documentation](docs/logging.md) was also added.
### New `--balloon` Parameter Added
@@ -2585,8 +2591,6 @@ Many thanks to everyone who has contributed to our 0.11.0 release including some
# v0.10.0
This release has been tracked through the [0.10.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/13).
Highlights for `cloud-hypervisor` version 0.10.0 include:
### `virtio-block` Support for Multiple Descriptors
@@ -2631,8 +2635,6 @@ Many thanks to everyone who has contributed to our 0.10.0 release including some
# v0.9.0
This release has been tracked through the [0.9.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/12).
Highlights for `cloud-hypervisor` version 0.9.0 include:
### `io_uring` Based Block Device Support
@@ -2714,8 +2716,6 @@ Many thanks to everyone who has contributed to our 0.9.0 release including some
# v0.8.0
This release has been tracked through the [0.8.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/10).
Highlights for `cloud-hypervisor` version 0.8.0 include:
### Experimental Snapshot and Restore Support
@@ -2735,7 +2735,7 @@ a VM using passthrough (VFIO) devices. Issues with SMP have also been observed
Included in this release is experimental support for running on ARM64.
Currently only `virtio-mmio` devices and a serial port are supported. Full
details can be found in the [ARM64 documentation](docs/arm64.md).
details can be found in the [ARM64 documentation](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/8ab15b9a984a448006f97b1211498c1bb583de3b/docs/arm64.md).
### Support for Using 5-level Paging in Guests
@@ -2804,8 +2804,6 @@ Many thanks to everyone who has contributed to our 0.8.0 release including some
# v0.7.0
This release has been tracked through the [0.7.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/7).
Highlights for `cloud-hypervisor` version 0.7.0 include:
### Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug
@@ -2903,8 +2901,6 @@ Many thanks to everyone who has contributed to our 0.7.0 release including some
# v0.6.0
This release has been tracked through the [0.6.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/7).
Highlights for `cloud-hypervisor` version 0.6.0 include:
### Directly Assigned Devices Hotplug
@@ -2981,8 +2977,6 @@ This is a bugfix release branched off v0.5.0. It contains the following fixes:
# v0.5.0
This release has been tracked through the [0.5.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/6).
Highlights for `cloud-hypervisor` version 0.5.0 include:
### Virtual Machine Dynamic Resizing
@@ -3042,8 +3036,6 @@ Many thanks to everyone that contributed to the 0.5.0 release:
# v0.4.0
This release has been tracked through the [0.4.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/4).
Highlights for `cloud-hypervisor` version 0.4.0 include:
### Dynamic virtual CPUs addition
@@ -3121,8 +3113,6 @@ Many thanks to everyone that contributed to the 0.4.0 release:
# v0.3.0
This release has been tracked through the [0.3.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/3).
Highlights for `cloud-hypervisor` version 0.3.0 include:
### Block device offloading
@@ -3190,8 +3180,6 @@ support guests with large amount of memory (more than 64GB).
# v0.2.0
This release has been tracked through the [0.2.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/2).
Highlights for `cloud-hypervisor` version 0.2.0 include:
### Network device offloading
@@ -3216,7 +3204,7 @@ enabled by default.
Based on the Firecracker idea of using a dedicated I/O port to measure guest
boot times, we added support for logging guest events through the
[0x80](https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
[0x80](https://web.archive.org/web/20211028033025/https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
PC debug port. This allows, among other things, for granular guest boot time
measurements. See our [debug port documentation](docs/debug-port.md) for more
details.
@@ -3244,8 +3232,6 @@ our CI pipeline.
# v0.1.0
This release has been tracked through the [0.1.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/1).
Highlights for `cloud-hypervisor` version 0.1.0 include:
### Shared filesystem

View File

@@ -5,10 +5,10 @@
# When changing this file don't forget to update the tag name in the
# .github/workflows/docker-image.yaml file if doing multiple per day
FROM ubuntu:22.04 as dev
FROM ubuntu:24.04 AS dev
ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.77.0"
ARG RUST_TOOLCHAIN="1.82.0"
ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
@@ -48,7 +48,6 @@ RUN apt-get update \
python3 \
python3-setuptools \
ntfs-3g \
python3-distutils \
uuid-dev \
iperf3 \
zip \
@@ -108,7 +107,9 @@ ENV OPENSSL_INCLUDE_DIR=/usr/include/
RUN export ARCH="$(uname -m)" \
&& nohup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "$RUST_TOOLCHAIN" \
&& rustup target add "$ARCH"-unknown-linux-musl --toolchain "$RUST_TOOLCHAIN" \
&& if [ "$TARGETARCH" = "amd64" ]; then rustup toolchain add --profile minimal $RUST_TOOLCHAIN-x86_64-unknown-linux-musl; fi \
&& if [ "$TARGETARCH" = "amd64" ]; then \
rustup toolchain add --profile minimal --force-non-host \
$RUST_TOOLCHAIN-x86_64-unknown-linux-musl; fi \
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add rustfmt; fi \
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add clippy; fi \
&& rm -rf "$CARGO_HOME/registry" \
@@ -122,25 +123,31 @@ RUN echo 'source $CARGO_HOME/env' >> "$HOME"/.bashrc \
&& mkdir "$HOME"/.cargo \
&& ln -s $CARGO_HOME/env "$HOME"/.cargo/env
# install SPDK NVMe
# only for 'x86_64' platform images as 'docker buildx' can't build 'spdk'
# Allow pip to install packages system wide
# hadolint ignore=DL3003,SC2046
RUN if [ "$TARGETARCH" = "amd64" ]; then \
git clone https://github.com/spdk/spdk \
&& cd spdk \
&& git checkout ef8bcce58f3f02b79c0619a297e4f17e81e62b24 \
&& git submodule update --init \
&& apt-get update \
&& ./scripts/pkgdep.sh \
&& apt-get clean \
&& ./configure --with-vfio-user \
&& make -j $(nproc) TARGET_ARCHITECTURE=skylake \
&& rm -rf /usr/local/bin/spdk-nvme \
&& mkdir /usr/local/bin/spdk-nvme \
&& cp -f ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
&& cp -f ./scripts/rpc.py /usr/local/bin/spdk-nvme \
&& cp -rf ./python /usr/local/bin \
&& cd .. && rm -rf spdk; fi
RUN rm /usr/lib/python3.12/EXTERNALLY-MANAGED \
&& git clone https://github.com/spdk/spdk \
&& cd spdk \
&& git checkout ef8bcce58f3f02b79c0619a297e4f17e81e62b24 \
&& git submodule update --init \
&& apt-get update \
&& ./scripts/pkgdep.sh \
&& apt-get clean \
&& ./configure --with-vfio-user \
&& if [ "$TARGETARCH" = "amd64" ]; then \
make -j $(nproc) TARGET_ARCHITECTURE=skylake; \
elif [ "$TARGETARCH" = "arm64" ]; then \
make -j $(nproc) TARGET_ARCHITECTURE="armv8.2-a" DPDKBUILD_FLAGS="-Dplatform=generic"; \
else \
echo "Unsupported architecture: ${TARGETARCH}" && exit 1; \
fi \
&& rm -rf /usr/local/bin/spdk-nvme \
&& mkdir /usr/local/bin/spdk-nvme \
&& cp -f ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
&& cp -f ./scripts/rpc.py /usr/local/bin/spdk-nvme \
&& cp -rf ./python/spdk/ /usr/local/bin/spdk-nvme \
&& cp -rf ./python /usr/local/bin \
&& cd .. && rm -rf spdk
# install ethr tool for performance tests
RUN if [ "$TARGETARCH" = "amd64" ]; then \

View File

@@ -9,7 +9,7 @@ CLI_NAME="Cloud Hypervisor"
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
# Needs to match explicit version in docker-image.yaml workflow
CTR_IMAGE_VERSION="20250111-0"
CTR_IMAGE_VERSION="20250307-2"
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
DOCKER_RUNTIME="docker"

View File

@@ -9,33 +9,6 @@ source "$(dirname "$0")"/common-aarch64.sh
WORKLOADS_LOCK="$WORKLOADS_DIR/integration_test.lock"
build_spdk_nvme() {
SPDK_DIR="$WORKLOADS_DIR/spdk"
SPDK_REPO="https://github.com/spdk/spdk.git"
SPDK_DEPLOY_DIR="/usr/local/bin/spdk-nvme"
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "ef8bcce58f3f02b79c0619a297e4f17e81e62b24"
if [ ! -f "$SPDK_DIR/.built" ]; then
pushd "$SPDK_DIR" || exit
git submodule update --init
apt-get update
sed -i "/grpcio/d" scripts/pkgdep/debian.sh
./scripts/pkgdep.sh
./configure --with-vfio-user
chmod +x /usr/local/lib/python3.10/dist-packages/ninja/data/bin/ninja
make -j "$(nproc)" || exit 1
touch .built
popd || exit
fi
if [ ! -d "/usr/local/bin/spdk-nvme" ]; then
mkdir -p $SPDK_DEPLOY_DIR
fi
cp "$WORKLOADS_DIR/spdk/build/bin/nvmf_tgt" $SPDK_DEPLOY_DIR/nvmf_tgt
cp "$WORKLOADS_DIR/spdk/scripts/rpc.py" $SPDK_DEPLOY_DIR/rpc.py
cp -r "$WORKLOADS_DIR/spdk/python/spdk/" $SPDK_DEPLOY_DIR/
cp -r "$WORKLOADS_DIR/spdk/python" $SPDK_DEPLOY_DIR/../
}
build_virtiofsd() {
VIRTIOFSD_DIR="$WORKLOADS_DIR/virtiofsd_build"
VIRTIOFSD_REPO="https://gitlab.com/virtio-fs/virtiofsd.git"
@@ -191,9 +164,6 @@ update_workloads() {
echo "bar" >"$SHARED_DIR/file3" || exit 1
fi
# Checkout and build SPDK NVMe
build_spdk_nvme
# Checkout and build EDK2
build_edk2
}

View File

@@ -176,58 +176,163 @@ fn default_rng() -> String {
format!("src={}", vm_config::DEFAULT_RNG_SOURCE)
}
fn create_app(default_vcpus: String, default_memory: String, default_rng: String) -> Command {
#[allow(clippy::let_and_return)]
let app = Command::new("cloud-hypervisor")
// 'BUILD_VERSION' is set by the build script 'build.rs' at
// compile time
.author(env!("CARGO_PKG_AUTHORS"))
.about("Launch a cloud-hypervisor VMM.")
.arg_required_else_help(true)
.group(ArgGroup::new("vm-config").multiple(true).requires("vm-payload"))
.group(ArgGroup::new("vmm-config").multiple(true))
.group(ArgGroup::new("logging").multiple(true))
.group(ArgGroup::new("vm-payload").multiple(true))
.arg(
Arg::new("cpus")
.long("cpus")
.help(
"boot=<boot_vcpus>,max=<max_vcpus>,\
/// Returns all [`Arg`]s in alphabetical order. This is the order used in the
/// `--help` output.
fn get_cli_options_sorted(
default_vcpus: String,
default_memory: String,
default_rng: String,
) -> Box<[Arg]> {
[
Arg::new("api-socket")
.long("api-socket")
.help("HTTP API socket (UNIX domain socket): path=</path/to/a/file> or fd=<fd>.")
.num_args(1)
.group("vmm-config"),
Arg::new("balloon")
.long("balloon")
.help(BalloonConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
Arg::new("cmdline")
.long("cmdline")
.help("Kernel command line")
.num_args(1)
.group("vm-config"), Arg::new("console")
.long("console")
.help(
"Control (virtio) console: \"off|null|pty|tty|file=</path/to/a/file>,iommu=on|off\"",
)
.default_value("tty")
.group("vm-config"),
Arg::new("cpus")
.long("cpus")
.help(
"boot=<boot_vcpus>,max=<max_vcpus>,\
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,\
kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,\
affinity=<list_of_vcpus_with_their_associated_cpuset>,\
features=<list_of_features_to_enable>",
)
.default_value(default_vcpus)
.group("vm-config"),
)
.arg(
Arg::new("platform")
.long("platform")
.help("num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,iommu_address_width=<bits>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("memory")
.long("memory")
.help(
"Memory parameters \
)
.default_value(default_vcpus)
.group("vm-config"),
#[cfg(target_arch = "x86_64")]
Arg::new("debug-console")
.long("debug-console")
.help("Debug console: off|pty|tty|file=</path/to/a/file>,iobase=<port in hex>")
.default_value("off,iobase=0xe9")
.group("vm-config"),
#[cfg(feature = "dbus_api")]
Arg::new("dbus-service-name")
.long("dbus-service-name")
.help("Well known name of the device")
.num_args(1)
.group("vmm-config"),
#[cfg(feature = "dbus_api")]
Arg::new("dbus-object-path")
.long("dbus-object-path")
.help("Object path to serve the dbus interface")
.num_args(1)
.group("vmm-config"),
#[cfg(feature = "dbus_api")]
Arg::new("dbus-system-bus")
.long("dbus-system-bus")
.action(ArgAction::SetTrue)
.help("Use the system bus instead of a session bus")
.num_args(0)
.group("vmm-config"),
Arg::new("device")
.long("device")
.help(DeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("disk")
.long("disk")
.help(DiskConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("event-monitor")
.long("event-monitor")
.help("File to report events on: path=</path/to/a/file> or fd=<fd>")
.num_args(1)
.group("vmm-config"),
Arg::new("firmware")
.long("firmware")
.help("Path to firmware that is loaded in an architectural specific way")
.num_args(1)
.group("vm-payload"),
Arg::new("fs")
.long("fs")
.help(FsConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
#[cfg(feature = "guest_debug")]
Arg::new("gdb")
.long("gdb")
.help("GDB socket (UNIX domain socket): path=</path/to/a/file>")
.num_args(1)
.group("vmm-config"),
#[cfg(feature = "igvm")]
Arg::new("igvm")
.long("igvm")
.help("Path to IGVM file to load.")
.num_args(1)
.group("vm-payload"),
#[cfg(feature = "sev_snp")]
Arg::new("host-data")
.long("host-data")
.help("Host specific data to SEV SNP guest")
.num_args(1)
.group("vm-config"),
Arg::new("initramfs")
.long("initramfs")
.help("Path to initramfs image")
.num_args(1)
.group("vm-config"),
Arg::new("kernel")
.long("kernel")
.help(
"Path to kernel to load. This may be a kernel or firmware that supports a PVH \
entry point (e.g. vmlinux) or architecture equivalent",
)
.num_args(1)
.group("vm-payload"),
Arg::new("landlock")
.long("landlock")
.num_args(0)
.help(
"enable/disable Landlock.",
)
.action(ArgAction::SetTrue)
.default_value("false")
.group("vm-config"),
Arg::new("landlock-rules")
.long("landlock-rules")
.help(LandlockConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("log-file")
.long("log-file")
.help("Log file. Standard error is used if not specified")
.num_args(1)
.group("logging"),
Arg::new("memory")
.long("memory")
.help(
"Memory parameters \
\"size=<guest_memory_size>,mergeable=on|off,shared=on|off,\
hugepages=on|off,hugepage_size=<hugepage_size>,\
hotplug_method=acpi|virtio-mem,\
hotplug_size=<hotpluggable_memory_size>,\
hotplugged_size=<hotplugged_memory_size>,\
prefault=on|off,thp=on|off\"",
)
.default_value(default_memory)
.group("vm-config"),
)
.arg(
Arg::new("memory-zone")
.long("memory-zone")
.help(
"User defined memory zone parameters \
)
.default_value(default_memory)
.group("vm-config"),
Arg::new("memory-zone")
.long("memory-zone")
.help(
"User defined memory zone parameters \
\"size=<guest_memory_region_size>,file=<backing_file>,\
shared=on|off,\
hugepages=on|off,hugepage_size=<hugepage_size>,\
@@ -235,319 +340,143 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,\
hotplugged_size=<hotplugged_memory_size>,\
prefault=on|off\"",
)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("firmware")
.long("firmware")
.help("Path to firmware that is loaded in an architectural specific way")
.num_args(1)
.group("vm-payload"),
)
.arg(
Arg::new("kernel")
.long("kernel")
.help(
"Path to kernel to load. This may be a kernel or firmware that supports a PVH \
entry point (e.g. vmlinux) or architecture equivalent",
)
.num_args(1)
.group("vm-payload"),
)
.arg(
Arg::new("initramfs")
.long("initramfs")
.help("Path to initramfs image")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("cmdline")
.long("cmdline")
.help("Kernel command line")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("rate-limit-group")
.long("rate-limit-group")
.help(RateLimiterGroupConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("disk")
.long("disk")
.help(DiskConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("landlock")
.long("landlock")
.num_args(0)
.help(
"enable/disable Landlock.",
)
.action(ArgAction::SetTrue)
.default_value("false")
.group("vm-config"),
)
.arg(
Arg::new("landlock-rules")
.long("landlock-rules")
.help(LandlockConfig::SYNTAX)
)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("net")
.long("net")
.help(NetConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("rng")
.long("rng")
.help(
"Random number generator parameters \"src=<entropy_source_path>,iommu=on|off\"",
)
.default_value(default_rng)
.group("vm-config"),
)
.arg(
Arg::new("balloon")
.long("balloon")
.help(BalloonConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("fs")
.long("fs")
.help(FsConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("pmem")
.long("pmem")
.help(PmemConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("serial")
.long("serial")
.help("Control serial port: off|null|pty|tty|file=</path/to/a/file>|socket=</path/to/a/file>")
.default_value("null")
.group("vm-config"),
)
.arg(
Arg::new("console")
.long("console")
.help(
"Control (virtio) console: \"off|null|pty|tty|file=</path/to/a/file>,iommu=on|off\"",
)
.default_value("tty")
.group("vm-config"),
)
.arg(
Arg::new("device")
.long("device")
.help(DeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("user-device")
.long("user-device")
.help(UserDeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("vdpa")
.long("vdpa")
.help(VdpaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("vsock")
.long("vsock")
.help(VsockConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("pvpanic")
.long("pvpanic")
.help("Enable pvpanic device")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
)
.arg(
Arg::new("numa")
.long("numa")
.help(NumaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("pci-segment")
.long("pci-segment")
.help(PciSegmentConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("watchdog")
.long("watchdog")
.help("Enable virtio-watchdog")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
)
.arg(
Arg::new("v")
.short('v')
.action(ArgAction::Count)
.help("Sets the level of debugging output")
.group("logging"),
)
.arg(
Arg::new("log-file")
.long("log-file")
.help("Log file. Standard error is used if not specified")
.num_args(1)
.group("logging"),
)
.arg(
Arg::new("api-socket")
.long("api-socket")
.help("HTTP API socket (UNIX domain socket): path=</path/to/a/file> or fd=<fd>.")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("event-monitor")
.long("event-monitor")
.help("File to report events on: path=</path/to/a/file> or fd=<fd>")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("restore")
.long("restore")
.help(RestoreConfig::SYNTAX)
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("seccomp")
.long("seccomp")
.num_args(1)
.value_parser(["true", "false", "log"])
.default_value("true"),
)
.arg(
Arg::new("tpm")
.long("tpm")
.num_args(1)
.help(TpmConfig::SYNTAX)
.group("vm-config"),
);
#[cfg(target_arch = "x86_64")]
let app = app.arg(
Arg::new("sgx-epc")
.long("sgx-epc")
.help(SgxEpcConfig::SYNTAX)
Arg::new("net")
.long("net")
.help(NetConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
);
#[cfg(target_arch = "x86_64")]
let app = app.arg(
Arg::new("debug-console")
.long("debug-console")
.help("Debug console: off|pty|tty|file=</path/to/a/file>,iobase=<port in hex>")
.default_value("off,iobase=0xe9")
Arg::new("numa")
.long("numa")
.help(NumaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
);
#[cfg(feature = "guest_debug")]
let app = app.arg(
Arg::new("gdb")
.long("gdb")
.help("GDB socket (UNIX domain socket): path=</path/to/a/file>")
.num_args(1)
.group("vmm-config"),
);
#[cfg(feature = "dbus_api")]
let app = app
.arg(
Arg::new("dbus-service-name")
.long("dbus-service-name")
.help("Well known name of the device")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("dbus-object-path")
.long("dbus-object-path")
.help("Object path to serve the dbus interface")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("dbus-system-bus")
.long("dbus-system-bus")
.action(ArgAction::SetTrue)
.help("Use the system bus instead of a session bus")
.num_args(0)
.group("vmm-config"),
);
#[cfg(feature = "igvm")]
let app = app.arg(
Arg::new("igvm")
.long("igvm")
.help("Path to IGVM file to load.")
.num_args(1)
.group("vm-payload"),
);
#[cfg(feature = "sev_snp")]
let app = app.arg(
Arg::new("host-data")
.long("host-data")
.help("Host specific data to SEV SNP guest")
Arg::new("pci-segment")
.long("pci-segment")
.help(PciSegmentConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("platform")
.long("platform")
.help(
"num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,iommu_address_width=<bits>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>"
)
.num_args(1)
.group("vm-config"),
);
#[cfg(feature = "pvmemcontrol")]
let app = app.arg(
Arg::new("pmem")
.long("pmem")
.help(PmemConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
#[cfg(feature = "pvmemcontrol")]
Arg::new("pvmemcontrol")
.long("pvmemcontrol")
.help("Pvmemcontrol device")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
);
app.arg(
Arg::new("pvpanic")
.long("pvpanic")
.help("Enable pvpanic device")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
Arg::new("rate-limit-group")
.long("rate-limit-group")
.help(RateLimiterGroupConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("restore")
.long("restore")
.help(RestoreConfig::SYNTAX)
.num_args(1)
.group("vmm-config"),
Arg::new("rng")
.long("rng")
.help(
"Random number generator parameters \"src=<entropy_source_path>,iommu=on|off\"",
)
.default_value(default_rng)
.group("vm-config"),
Arg::new("seccomp")
.long("seccomp")
.num_args(1)
.value_parser(["true", "false", "log"])
.default_value("true"),
Arg::new("serial")
.long("serial")
.help("Control serial port: off|null|pty|tty|file=</path/to/a/file>|socket=</path/to/a/file>")
.default_value("null")
.group("vm-config"),
#[cfg(target_arch = "x86_64")]
Arg::new("sgx-epc")
.long("sgx-epc")
.help(SgxEpcConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("tpm")
.long("tpm")
.num_args(1)
.help(TpmConfig::SYNTAX)
.group("vm-config"),
Arg::new("user-device")
.long("user-device")
.help(UserDeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("v")
.short('v')
.action(ArgAction::Count)
.help("Sets the level of debugging output")
.group("logging"),
Arg::new("vdpa")
.long("vdpa")
.help(VdpaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
Arg::new("version")
.short('V')
.long("version")
.action(ArgAction::SetTrue)
.help("Print version")
.num_args(0),
)
Arg::new("vsock")
.long("vsock")
.help(VsockConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
Arg::new("watchdog")
.long("watchdog")
.help("Enable virtio-watchdog")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
].to_vec().into_boxed_slice()
}
/// Creates the CLI definition of Cloud Hypervisor.
fn create_app(default_vcpus: String, default_memory: String, default_rng: String) -> Command {
let groups = [
ArgGroup::new("vm-config")
.multiple(true)
.requires("vm-payload"),
ArgGroup::new("vmm-config").multiple(true),
ArgGroup::new("logging").multiple(true),
ArgGroup::new("vm-payload").multiple(true),
];
let args = get_cli_options_sorted(default_vcpus, default_memory, default_rng);
Command::new("cloud-hypervisor")
// 'BUILD_VERSION' is set by the build script 'build.rs' at
// compile time
.author(env!("CARGO_PKG_AUTHORS"))
.about("Launch a cloud-hypervisor VMM.")
.arg_required_else_help(true)
.groups(groups)
.args(args)
}
fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
@@ -965,6 +894,7 @@ fn main() {
#[cfg(test)]
mod unit_tests {
use std::cmp::Ordering;
use std::path::PathBuf;
use vmm::config::VmParams;
@@ -975,7 +905,7 @@ mod unit_tests {
PayloadConfig, RngConfig, VmConfig,
};
use crate::{create_app, prepare_default_values};
use crate::{create_app, get_cli_options_sorted, prepare_default_values};
fn get_vm_config_from_vec(args: &[&str]) -> VmConfig {
let (default_vcpus, default_memory, default_rng) = prepare_default_values();
@@ -2075,4 +2005,24 @@ mod unit_tests {
compare_vm_config_cli_vs_json(cli, openapi, *equal);
});
}
// TODO the check for the option list being sorted could be moved into the
// getter itself, when the getter becomes a const function. This however
// needs more support by Rust (as of March 2025).
#[test]
fn test_cli_options_sorted() {
let (default_vcpus, default_memory, default_rng) = prepare_default_values();
let args = get_cli_options_sorted(default_vcpus, default_memory, default_rng);
let iter = args.iter().zip(args.iter().skip(1));
for (elem, next) in iter {
assert_ne!(
elem.get_id().cmp(next.get_id()),
Ordering::Greater,
"items not alphabetically sorted: elem={}, next={}",
elem.get_id(),
next.get_id()
);
}
}
}

View File

@@ -5,7 +5,7 @@ name = "test_infra"
version = "0.1.0"
[dependencies]
dirs = "5.0.1"
dirs = "6.0.0"
epoll = "4.3.3"
libc = "0.2.167"
once_cell = "1.20.2"

View File

@@ -7587,6 +7587,7 @@ mod common_sequential {
}
#[test]
#[cfg_attr(target_arch = "aarch64", ignore = "See #6970")]
fn test_snapshot_restore_with_fd() {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));

View File

@@ -108,7 +108,7 @@ struct PartiallyBalloonedPage {
impl PartiallyBalloonedPage {
fn new() -> Self {
let page_size = get_page_size();
let len = ((page_size >> VIRTIO_BALLOON_PFN_SHIFT) + 63) / 64;
let len = (page_size >> VIRTIO_BALLOON_PFN_SHIFT).div_ceil(64);
// Initial each padding bit as 1 in bitmap.
let mut bitmap = vec![0_u64; len as usize];
let pad_num = len * 64 - (page_size >> VIRTIO_BALLOON_PFN_SHIFT);
@@ -134,7 +134,7 @@ impl PartiallyBalloonedPage {
}
fn reset(&mut self) {
let len = ((self.page_size >> VIRTIO_BALLOON_PFN_SHIFT) + 63) / 64;
let len = (self.page_size >> VIRTIO_BALLOON_PFN_SHIFT).div_ceil(64);
self.addr = 0;
self.bitmap = vec![0; len as usize];
let pad_num = len * 64 - (self.page_size >> VIRTIO_BALLOON_PFN_SHIFT);

View File

@@ -146,9 +146,9 @@ where
/// Returns:
/// - `Ok(())`: the packet has been successfully filled in and is ready for delivery;
/// - `Err(VsockError::NoData)`: there was no data available with which to fill in the
/// packet;
/// packet;
/// - `Err(VsockError::PktBufMissing)`: the packet would've been filled in with data, but
/// it is missing the data buffer.
/// it is missing the data buffer.
///
fn recv_pkt(&mut self, pkt: &mut VsockPacket) -> VsockResult<()> {
// Perform some generic initialization that is the same for any packet operation (e.g.

View File

@@ -191,7 +191,7 @@ pub trait Transportable: Pausable + Snapshottable {
///
/// * `snapshot` - The migratable component snapshot to send.
/// * `destination_url` - The destination URL to send the snapshot to. This
/// could be an HTTP endpoint, a TCP address or a local file.
/// could be an HTTP endpoint, a TCP address or a local file.
fn send(
&self,
_snapshot: &Snapshot,
@@ -205,7 +205,7 @@ pub trait Transportable: Pausable + Snapshottable {
/// # Arguments
///
/// * `source_url` - The source URL to fetch the snapshot from. This could be an HTTP
/// endpoint, a TCP address or a local file.
/// endpoint, a TCP address or a local file.
fn recv(&self, _source_url: &str) -> std::result::Result<Snapshot, MigratableError> {
Ok(Snapshot::default())
}

View File

@@ -44,8 +44,8 @@ gdbstub = { version = "0.7.1", optional = true }
gdbstub_arch = { version = "0.3.0", optional = true }
hex = { version = "0.4.3", optional = true }
hypervisor = { path = "../hypervisor" }
igvm = { version = "0.3.3", optional = true }
igvm_defs = { version = "0.3.1", optional = true }
igvm = { workspace = true, optional = true }
igvm_defs = { workspace = true, optional = true }
landlock = "0.4.0"
libc = "0.2.167"
linux-loader = { workspace = true, features = ["bzimage", "elf", "pe"] }

View File

@@ -548,6 +548,10 @@ components:
type: string
initramfs:
type: string
igvm:
type: string
host_data:
type: string
description: Payloads to boot in guest
VmConfig:
@@ -732,6 +736,9 @@ components:
tdx:
type: boolean
default: false
sev_snp:
type: boolean
default: false
MemoryZoneConfig:
required:

View File

@@ -21,6 +21,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier, Mutex};
use std::{cmp, io, result, thread};
#[cfg(not(target_arch = "riscv64"))]
use acpi_tables::sdt::Sdt;
use acpi_tables::{aml, Aml};
use anyhow::anyhow;
@@ -44,10 +45,6 @@ use hypervisor::arch::x86::CpuIdEntry;
use hypervisor::arch::x86::MsrEntry;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use hypervisor::arch::x86::SpecialRegisters;
#[cfg(target_arch = "aarch64")]
use hypervisor::kvm::kvm_bindings;
#[cfg(all(target_arch = "aarch64", feature = "kvm"))]
use hypervisor::kvm::kvm_ioctls::Cap;
#[cfg(feature = "tdx")]
use hypervisor::kvm::{TdxExitDetails, TdxExitStatus};
#[cfg(target_arch = "x86_64")]
@@ -138,6 +135,10 @@ pub enum Error {
#[error("Error fetching preferred target: {0}")]
VcpuArmPreferredTarget(#[source] hypervisor::HypervisorVmError),
#[cfg(target_arch = "aarch64")]
#[error("Error setting vCPU processor features: {0}")]
VcpuSetProcessorFeatures(#[source] hypervisor::HypervisorCpuError),
#[cfg(target_arch = "aarch64")]
#[error("Error initialising vCPU: {0}")]
VcpuArmInit(#[source] hypervisor::HypervisorCpuError),
@@ -390,6 +391,8 @@ impl Vcpu {
self.mpidr = arch::configure_vcpu(&self.vcpu, self.id, boot_setup)
.map_err(Error::VcpuConfiguration)?;
}
#[cfg(target_arch = "riscv64")]
arch::configure_vcpu(&self.vcpu, self.id, boot_setup).map_err(Error::VcpuConfiguration)?;
info!("Configuring vCPU: cpu_id = {}", self.id);
#[cfg(target_arch = "x86_64")]
arch::configure_vcpu(
@@ -413,7 +416,7 @@ impl Vcpu {
}
/// Gets the saved vCPU state.
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
pub fn get_saved_state(&self) -> Option<CpuState> {
self.saved_state.clone()
}
@@ -422,42 +425,25 @@ impl Vcpu {
#[cfg(target_arch = "aarch64")]
pub fn init(&self, vm: &Arc<dyn hypervisor::Vm>) -> Result<()> {
use std::arch::is_aarch64_feature_detected;
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
#[allow(clippy::nonminimal_bool)]
let sve_supported =
is_aarch64_feature_detected!("sve") || is_aarch64_feature_detected!("sve2");
let mut kvi = self.vcpu.create_vcpu_init();
// This reads back the kernel's preferred target type.
vm.get_preferred_target(&mut kvi)
.map_err(Error::VcpuArmPreferredTarget)?;
// We already checked that the capability is supported.
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2;
if vm
.as_any()
.downcast_ref::<hypervisor::kvm::KvmVm>()
.unwrap()
.check_extension(Cap::ArmPmuV3)
{
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PMU_V3;
}
if sve_supported
&& vm
.as_any()
.downcast_ref::<hypervisor::kvm::KvmVm>()
.unwrap()
.check_extension(Cap::ArmSve)
{
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_SVE;
}
self.vcpu
.vcpu_set_processor_features(vm, &mut kvi, self.id)
.map_err(Error::VcpuSetProcessorFeatures)?;
// Non-boot cpus are powered off initially.
if self.id > 0 {
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
}
self.vcpu.vcpu_init(&kvi).map_err(Error::VcpuArmInit)?;
if sve_supported {
let finalized_features = self.vcpu.vcpu_get_finalized_features();
self.vcpu
.vcpu_finalize(kvm_bindings::KVM_ARM_VCPU_SVE as i32)
.vcpu_finalize(finalized_features)
.map_err(Error::VcpuArmFinalize)?;
}
Ok(())
@@ -814,7 +800,7 @@ impl CpuManager {
let topology = self.get_vcpu_topology();
#[cfg(target_arch = "x86_64")]
let x2apic_id = arch::x86_64::get_x2apic_id(cpu_id as u32, topology);
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
let x2apic_id = cpu_id as u32;
let mut vcpu = Vcpu::new(
@@ -888,6 +874,9 @@ impl CpuManager {
#[cfg(target_arch = "aarch64")]
vcpu.configure(&self.vm, boot_setup)?;
#[cfg(target_arch = "riscv64")]
vcpu.configure(boot_setup)?;
Ok(())
}
@@ -1413,6 +1402,7 @@ impl CpuManager {
.map(|t| (t.threads_per_core, t.cores_per_die, t.packages))
}
#[cfg(not(target_arch = "riscv64"))]
pub fn create_madt(&self) -> Sdt {
use crate::acpi;
// This is also checked in the commandline parsing.
@@ -2950,8 +2940,7 @@ mod tests {
use arch::layout;
use hypervisor::kvm::aarch64::is_system_register;
use hypervisor::kvm::kvm_bindings::{
kvm_vcpu_init, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM_CORE,
KVM_REG_SIZE_U64,
user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
};
use hypervisor::{arm64_core_reg_id, offset_of};
@@ -2964,7 +2953,7 @@ mod tests {
// Must fail when vcpu is not initialized yet.
vcpu.setup_regs(0, 0x0, layout::FDT_START.0).unwrap_err();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = vcpu.create_vcpu_init();
vm.get_preferred_target(&mut kvi).unwrap();
vcpu.vcpu_init(&kvi).unwrap();
@@ -2976,7 +2965,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = vcpu.create_vcpu_init();
vm.get_preferred_target(&mut kvi).unwrap();
// Must fail when vcpu is not initialized yet.
@@ -3000,7 +2989,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = vcpu.create_vcpu_init();
vm.get_preferred_target(&mut kvi).unwrap();
// Must fail when vcpu is not initialized yet.
@@ -3027,7 +3016,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let vcpu = vm.create_vcpu(0, None).unwrap();
let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default();
let mut kvi = vcpu.create_vcpu_init();
vm.get_preferred_target(&mut kvi).unwrap();
let state = vcpu.get_mp_state().unwrap();

View File

@@ -18,15 +18,18 @@ use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::PathBuf;
use std::result;
use std::sync::{Arc, Mutex};
#[cfg(not(target_arch = "riscv64"))]
use std::time::Instant;
use acpi_tables::sdt::GenericAddress;
#[cfg(not(target_arch = "riscv64"))]
use acpi_tables::{aml, Aml};
#[cfg(not(target_arch = "riscv64"))]
use anyhow::anyhow;
#[cfg(target_arch = "x86_64")]
use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START};
use arch::{layout, NumaNodes};
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use arch::{DeviceType, MmioDeviceInfo};
use block::async_io::DiskFile;
use block::fixed_vhd_sync::FixedVhdDiskSync;
@@ -39,6 +42,10 @@ use block::{
};
#[cfg(feature = "io_uring")]
use block::{fixed_vhd_async::FixedVhdDiskAsync, raw_async::RawFileDisk};
#[cfg(target_arch = "riscv64")]
use devices::aia;
#[cfg(target_arch = "x86_64")]
use devices::debug_console;
#[cfg(target_arch = "x86_64")]
use devices::debug_console::DebugConsole;
#[cfg(target_arch = "aarch64")]
@@ -48,6 +55,8 @@ use devices::interrupt_controller::InterruptController;
use devices::ioapic;
#[cfg(target_arch = "aarch64")]
use devices::legacy::Pl011;
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
use devices::legacy::Serial;
#[cfg(feature = "pvmemcontrol")]
use devices::pvmemcontrol::{PvmemcontrolBusDevice, PvmemcontrolPciDevice};
use devices::{interrupt_controller, AcpiNotificationFlags};
@@ -88,8 +97,6 @@ use vm_migration::{
};
use vm_virtio::{AccessPlatform, VirtioDeviceType};
use vmm_sys_util::eventfd::EventFd;
#[cfg(target_arch = "x86_64")]
use {devices::debug_console, devices::legacy::Serial};
use crate::console_devices::{ConsoleDeviceError, ConsoleInfo, ConsoleOutput};
use crate::cpu::{CpuManager, CPU_MANAGER_ACPI_SIZE};
@@ -105,7 +112,7 @@ use crate::vm_config::{
};
use crate::{device_node, GuestRegionMmap, PciDeviceInfo, DEVICE_MANAGER_SNAPSHOT_ID};
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
const MMIO_LEN: u64 = 0x1000;
// Singleton devices / devices the user cannot name
@@ -823,9 +830,11 @@ pub struct DeviceManager {
interrupt_controller: Option<Arc<Mutex<ioapic::Ioapic>>>,
#[cfg(target_arch = "aarch64")]
interrupt_controller: Option<Arc<Mutex<gic::Gic>>>,
#[cfg(target_arch = "riscv64")]
interrupt_controller: Option<Arc<Mutex<aia::Aia>>>,
// Things to be added to the commandline (e.g. aarch64 early console)
#[cfg(target_arch = "aarch64")]
// Things to be added to the commandline (e.g. aarch64 or riscv64 early console)
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
cmdline_additions: Vec<String>,
// ACPI GED notification device
@@ -888,7 +897,7 @@ pub struct DeviceManager {
exit_evt: EventFd,
reset_evt: EventFd,
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
id_to_dev_info: HashMap<(DeviceType, String), MmioDeviceInfo>,
// seccomp action
@@ -904,6 +913,7 @@ pub struct DeviceManager {
// activation and thus start the threads from the VMM thread
activate_evt: EventFd,
#[cfg(not(target_arch = "riscv64"))]
acpi_address: GuestAddress,
selected_segment: usize,
@@ -936,12 +946,14 @@ pub struct DeviceManager {
// List of unique identifiers provided at boot through the configuration.
boot_id_list: BTreeSet<String>,
#[cfg(not(target_arch = "riscv64"))]
// Start time of the VM
timestamp: Instant,
// Pending activations
pending_activations: Arc<Mutex<Vec<VirtioPciDeviceActivator>>>,
#[cfg(not(target_arch = "riscv64"))]
// Addresses for ACPI platform devices e.g. ACPI PM timer, sleep/reset registers
acpi_platform_addresses: AcpiPlatformAddresses,
@@ -996,7 +1008,7 @@ impl DeviceManager {
activate_evt: &EventFd,
force_iommu: bool,
boot_id_list: BTreeSet<String>,
timestamp: Instant,
#[cfg(not(target_arch = "riscv64"))] timestamp: Instant,
snapshot: Option<Snapshot>,
dynamic: bool,
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
@@ -1020,8 +1032,7 @@ impl DeviceManager {
};
let mut mmio32_aperture_weights: Vec<u32> =
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
.take(num_pci_segments.into())
std::iter::repeat_n(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT, num_pci_segments.into())
.collect();
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
for pci_segment in pci_segments.iter() {
@@ -1041,8 +1052,7 @@ impl DeviceManager {
);
let mut mmio64_aperture_weights: Vec<u32> =
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
.take(num_pci_segments.into())
std::iter::repeat_n(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT, num_pci_segments.into())
.collect();
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
for pci_segment in pci_segments.iter() {
@@ -1163,7 +1173,7 @@ impl DeviceManager {
address_manager: Arc::clone(&address_manager),
console: Arc::new(Console::default()),
interrupt_controller: None,
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
cmdline_additions: Vec::new(),
ged_notification_device: None,
config,
@@ -1183,7 +1193,7 @@ impl DeviceManager {
device_tree,
exit_evt,
reset_evt,
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
id_to_dev_info: HashMap::new(),
seccomp_action,
numa_nodes,
@@ -1191,6 +1201,7 @@ impl DeviceManager {
activate_evt: activate_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
#[cfg(not(target_arch = "riscv64"))]
acpi_address,
selected_segment: 0,
serial_manager: None,
@@ -1206,8 +1217,10 @@ impl DeviceManager {
io_uring_supported: None,
aio_supported: None,
boot_id_list,
#[cfg(not(target_arch = "riscv64"))]
timestamp,
pending_activations: Arc::new(Mutex::new(Vec::default())),
#[cfg(not(target_arch = "riscv64"))]
acpi_platform_addresses: AcpiPlatformAddresses::default(),
snapshot,
rate_limit_groups,
@@ -1301,6 +1314,7 @@ impl DeviceManager {
console_resize_pipe,
)?;
#[cfg(not(target_arch = "riscv64"))]
if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() {
let tpm_dev = self.add_tpm_device(tpm.socket.clone())?;
self.bus_devices
@@ -1349,11 +1363,21 @@ impl DeviceManager {
vgic_config.msi_addr + vgic_config.msi_size - 1,
)
}
#[cfg(target_arch = "riscv64")]
{
let vcpus = self.config.lock().unwrap().cpus.boot_vcpus;
let vaia_config = aia::Aia::create_default_config(vcpus.into());
(
vaia_config.imsic_addr,
vaia_config.imsic_addr + vaia_config.vcpu_count as u64 * arch::layout::IMSIC_SIZE
- 1,
)
}
#[cfg(target_arch = "x86_64")]
(0xfee0_0000, 0xfeef_ffff)
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
/// Gets the information of the devices registered up to some point in time.
pub fn get_device_info(&self) -> &HashMap<(DeviceType, String), MmioDeviceInfo> {
&self.id_to_dev_info
@@ -1518,6 +1542,43 @@ impl DeviceManager {
self.interrupt_controller.as_ref()
}
#[cfg(target_arch = "riscv64")]
fn add_interrupt_controller(
&mut self,
) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> {
let interrupt_controller: Arc<Mutex<aia::Aia>> = Arc::new(Mutex::new(
aia::Aia::new(
self.config.lock().unwrap().cpus.boot_vcpus,
Arc::clone(&self.msi_interrupt_manager),
self.address_manager.vm.clone(),
)
.map_err(DeviceManagerError::CreateInterruptController)?,
));
self.interrupt_controller = Some(interrupt_controller.clone());
// Restore the vAia if this is in the process of restoration
let id = String::from(aia::_AIA_SNAPSHOT_ID);
if let Some(_vaia_snapshot) = snapshot_from_id(self.snapshot.as_ref(), &id) {
// TODO: vAia snapshotting and restoration is scheduled to next stage of riscv64 support.
// TODO: PMU support is scheduled to next stage of riscv64 support.
// PMU support is optional. Nothing should be impacted if the PMU initialization failed.
unimplemented!()
}
self.device_tree
.lock()
.unwrap()
.insert(id.clone(), device_node!(id, interrupt_controller));
Ok(interrupt_controller)
}
#[cfg(target_arch = "riscv64")]
pub fn get_interrupt_controller(&mut self) -> Option<&Arc<Mutex<aia::Aia>>> {
self.interrupt_controller.as_ref()
}
#[cfg(target_arch = "x86_64")]
fn add_interrupt_controller(
&mut self,
@@ -1997,6 +2058,69 @@ impl DeviceManager {
Ok(serial)
}
#[cfg(target_arch = "riscv64")]
fn add_serial_device(
&mut self,
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
serial_writer: Option<Box<dyn io::Write + Send>>,
) -> DeviceManagerResult<Arc<Mutex<Serial>>> {
let id = String::from(SERIAL_DEVICE_NAME);
let serial_irq = self
.address_manager
.allocator
.lock()
.unwrap()
.allocate_irq()
.unwrap();
let interrupt_group = interrupt_manager
.create_group(LegacyIrqGroupConfig {
irq: serial_irq as InterruptIndex,
})
.map_err(DeviceManagerError::CreateInterruptGroup)?;
let serial = Arc::new(Mutex::new(Serial::new(
id.clone(),
interrupt_group,
serial_writer,
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)));
self.bus_devices
.push(Arc::clone(&serial) as Arc<dyn BusDeviceSync>);
let addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START;
self.address_manager
.mmio_bus
.insert(serial.clone(), addr.0, MMIO_LEN)
.map_err(DeviceManagerError::BusError)?;
self.id_to_dev_info.insert(
(DeviceType::Serial, DeviceType::Serial.to_string()),
MmioDeviceInfo {
addr: addr.0,
len: MMIO_LEN,
irq: serial_irq,
},
);
self.cmdline_additions
.push(format!("earlycon=uart,mmio,0x{:08x}", addr.0));
// Fill the device tree with a new node. In case of restore, we
// know there is nothing to do, so we can simply override the
// existing entry.
self.device_tree
.lock()
.unwrap()
.insert(id.clone(), device_node!(id, serial));
Ok(serial)
}
fn add_virtio_console_device(
&mut self,
virtio_devices: &mut Vec<MetaVirtioDevice>,
@@ -2161,6 +2285,7 @@ impl DeviceManager {
Ok(Arc::new(Console { console_resizer }))
}
#[cfg(not(target_arch = "riscv64"))]
fn add_tpm_device(
&mut self,
tpm_path: PathBuf,
@@ -3433,6 +3558,7 @@ impl DeviceManager {
memory_manager.lock().unwrap().memory_slot_allocator(),
vm_migration::snapshot_from_id(self.snapshot.as_ref(), vfio_name.as_str()),
device_cfg.x_nv_gpudirect_clique,
device_cfg.path.clone(),
)
.map_err(DeviceManagerError::VfioPciCreate)?;
@@ -3906,7 +4032,7 @@ impl DeviceManager {
&self.pci_segments
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
pub fn cmdline_additions(&self) -> &[String] {
self.cmdline_additions.as_slice()
}
@@ -4492,6 +4618,7 @@ impl DeviceManager {
Ok(())
}
#[cfg(not(target_arch = "riscv64"))]
pub(crate) fn acpi_platform_addresses(&self) -> &AcpiPlatformAddresses {
&self.acpi_platform_addresses
}
@@ -4517,8 +4644,10 @@ fn numa_node_id_from_pci_segment_id(numa_nodes: &NumaNodes, pci_segment_id: u16)
0
}
#[cfg(not(target_arch = "riscv64"))]
struct TpmDevice {}
#[cfg(not(target_arch = "riscv64"))]
impl Aml for TpmDevice {
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
aml::Device::new(
@@ -4540,6 +4669,7 @@ impl Aml for TpmDevice {
}
}
#[cfg(not(target_arch = "riscv64"))]
impl Aml for DeviceManager {
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
#[cfg(target_arch = "aarch64")]

View File

@@ -19,6 +19,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
use std::sync::{Arc, Mutex};
#[cfg(not(target_arch = "riscv64"))]
use std::time::Instant;
use std::{io, result, thread};
@@ -64,6 +65,7 @@ use crate::vm_config::{
VmConfig, VsockConfig,
};
#[cfg(not(target_arch = "riscv64"))]
mod acpi;
pub mod api;
mod clone3;
@@ -940,6 +942,7 @@ impl Vmm {
MigratableError::MigrateReceive(anyhow!("Error cloning activate EventFd: {}", e))
})?;
#[cfg(not(target_arch = "riscv64"))]
let timestamp = Instant::now();
let hypervisor_vm = mm.lock().unwrap().vm.clone();
let mut vm = Vm::new_from_memory_manager(
@@ -953,6 +956,7 @@ impl Vmm {
&self.seccomp_action,
self.hypervisor.clone(),
activate_evt,
#[cfg(not(target_arch = "riscv64"))]
timestamp,
self.console_info.clone(),
self.console_resize_pipe.clone(),
@@ -1205,9 +1209,6 @@ impl Vmm {
// Send last batch of dirty pages
Self::vm_maybe_send_dirty_pages(vm, &mut socket)?;
// Stop logging dirty pages
vm.stop_dirty_log()?;
}
// Capture snapshot and send it
let vm_snapshot = vm.snapshot()?;
@@ -1227,6 +1228,11 @@ impl Vmm {
MigratableError::MigrateSend(anyhow!("Error completing migration")),
)?;
// Stop logging dirty pages
if !send_data_migration.local {
vm.stop_dirty_log()?;
}
info!("Migration complete");
// Let every Migratable object know about the migration being complete
@@ -2278,14 +2284,16 @@ impl RequestHandler for Vmm {
vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
self.hypervisor.clone(),
send_data_migration,
send_data_migration.clone(),
)
.map_err(|migration_err| {
error!("Migration failed: {:?}", migration_err);
// Stop logging dirty pages
if let Err(e) = vm.stop_dirty_log() {
return e;
// Stop logging dirty pages only for non-local migrations
if !send_data_migration.local {
if let Err(e) = vm.stop_dirty_log() {
return e;
}
}
if vm.get_state().unwrap() == VmState::Paused {

View File

@@ -1246,6 +1246,11 @@ impl MemoryManager {
memory_manager.add_uefi_flash()?;
}
#[cfg(target_arch = "riscv64")]
{
memory_manager.allocate_address_space()?;
}
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epc_config) = sgx_epc_config {
memory_manager.setup_sgx(sgx_epc_config)?;
@@ -1607,6 +1612,7 @@ impl MemoryManager {
.checked_add(1)
.ok_or(Error::GuestAddressOverFlow)?;
#[cfg(not(target_arch = "riscv64"))]
if mem_end < arch::layout::MEM_32BIT_RESERVED_START {
return Ok(arch::layout::RAM_64BIT_START);
}

View File

@@ -141,7 +141,7 @@ impl PciSegment {
Ok(segment)
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
pub(crate) fn new_default_segment(
address_manager: &Arc<AddressManager>,
mem32_allocator: Arc<Mutex<AddressAllocator>>,

View File

@@ -166,6 +166,12 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
MSHV_INITIALIZE_PARTITION()
)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_GUEST_MEMORY())?],
and![Cond::new(
1,
ArgLen::Dword,
Eq,
MSHV_GET_HOST_PARTITION_PROPERTY()
)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_VP())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IRQFD())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_IOEVENTFD())?],
@@ -173,7 +179,9 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_REGISTERS())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_VP_REGISTERS())?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_RUN_VP())?],
#[cfg(target_arch = "x86_64")]
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_VP_STATE())?],
#[cfg(target_arch = "x86_64")]
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_SET_VP_STATE())?],
and![Cond::new(
1,
@@ -194,6 +202,7 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
MSHV_GET_GPAP_ACCESS_BITMAP()
)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA())?],
#[cfg(target_arch = "x86_64")]
and![Cond::new(
1,
ArgLen::Dword,
@@ -447,7 +456,13 @@ fn create_vmm_ioctl_seccomp_rule_kvm() -> Result<Vec<SeccompRule>, BackendError>
Ok(arch_rules)
}
#[cfg(all(target_arch = "x86_64", feature = "mshv"))]
#[cfg(all(target_arch = "riscv64", feature = "kvm"))]
fn create_vmm_ioctl_seccomp_rule_kvm() -> Result<Vec<SeccompRule>, BackendError> {
let common_rules = create_vmm_ioctl_seccomp_rule_common(HypervisorType::Kvm)?;
Ok(common_rules)
}
#[cfg(feature = "mshv")]
fn create_vmm_ioctl_seccomp_rule_mshv() -> Result<Vec<SeccompRule>, BackendError> {
create_vmm_ioctl_seccomp_rule_common(HypervisorType::Mshv)
}
@@ -825,6 +840,7 @@ fn http_api_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError>
Ok(vec![
(libc::SYS_accept4, vec![]),
(libc::SYS_brk, vec![]),
(libc::SYS_clock_gettime, vec![]),
(libc::SYS_close, vec![]),
(libc::SYS_dup, vec![]),
(libc::SYS_epoll_create1, vec![]),

View File

@@ -16,7 +16,7 @@ use std::{io, result, thread};
#[cfg(target_arch = "aarch64")]
use devices::legacy::Pl011;
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
use devices::legacy::Serial;
use libc::EFD_NONBLOCK;
use serial_buffer::SerialBuffer;
@@ -108,7 +108,7 @@ impl From<u64> for EpollDispatch {
}
pub struct SerialManager {
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
serial: Arc<Mutex<Serial>>,
#[cfg(target_arch = "aarch64")]
serial: Arc<Mutex<Pl011>>,
@@ -122,7 +122,7 @@ pub struct SerialManager {
impl SerialManager {
pub fn new(
#[cfg(target_arch = "x86_64")] serial: Arc<Mutex<Serial>>,
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] serial: Arc<Mutex<Serial>>,
#[cfg(target_arch = "aarch64")] serial: Arc<Mutex<Pl011>>,
mut output: ConsoleOutput,
socket: Option<PathBuf>,
@@ -226,7 +226,7 @@ impl SerialManager {
// after the connection happened, and if that's the case it flushes
// all output from the serial to the PTY. Otherwise, it's a no-op.
fn trigger_pty_flush(
#[cfg(target_arch = "x86_64")] serial: &Arc<Mutex<Serial>>,
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] serial: &Arc<Mutex<Serial>>,
#[cfg(target_arch = "aarch64")] serial: &Arc<Mutex<Pl011>>,
pty_write_out: Option<&Arc<AtomicBool>>,
) -> Result<()> {

View File

@@ -20,6 +20,7 @@ use std::num::Wrapping;
use std::ops::Deref;
use std::os::unix::net::UnixStream;
use std::sync::{Arc, Mutex, RwLock};
#[cfg(not(target_arch = "riscv64"))]
use std::time::Instant;
use std::{cmp, result, str, thread};
@@ -28,7 +29,7 @@ use anyhow::anyhow;
use arch::layout::{KVM_IDENTITY_MAP_START, KVM_TSS_START};
#[cfg(feature = "tdx")]
use arch::x86_64::tdx::TdvfSection;
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use arch::PciSpaceInfo;
use arch::{get_host_cpu_phys_bits, EntryPoint, NumaNode, NumaNodes};
#[cfg(target_arch = "aarch64")]
@@ -47,7 +48,7 @@ use linux_loader::elf;
use linux_loader::loader::bzimage::BzImage;
#[cfg(target_arch = "x86_64")]
use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent;
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use linux_loader::loader::pe::Error::InvalidImageMagicNumber;
use linux_loader::loader::KernelLoader;
use seccompiler::SeccompAction;
@@ -466,8 +467,10 @@ pub struct Vm {
vm: Arc<dyn hypervisor::Vm>,
#[cfg(target_arch = "x86_64")]
saved_clock: Option<hypervisor::ClockData>,
#[cfg(not(target_arch = "riscv64"))]
numa_nodes: NumaNodes,
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
#[cfg(not(target_arch = "riscv64"))]
hypervisor: Arc<dyn hypervisor::Hypervisor>,
stop_on_boot: bool,
load_payload_handle: Option<thread::JoinHandle<Result<EntryPoint>>>,
@@ -487,7 +490,7 @@ impl Vm {
seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>,
activate_evt: EventFd,
timestamp: Instant,
#[cfg(not(target_arch = "riscv64"))] timestamp: Instant,
console_info: Option<ConsoleInfo>,
console_resize_pipe: Option<Arc<File>>,
original_termios: Arc<Mutex<Option<termios>>>,
@@ -634,6 +637,7 @@ impl Vm {
&activate_evt,
force_iommu,
boot_id_list,
#[cfg(not(target_arch = "riscv64"))]
timestamp,
snapshot_from_id(snapshot.as_ref(), DEVICE_MANAGER_SNAPSHOT_ID),
dynamic,
@@ -694,7 +698,9 @@ impl Vm {
vm,
#[cfg(target_arch = "x86_64")]
saved_clock,
#[cfg(not(target_arch = "riscv64"))]
numa_nodes,
#[cfg(not(target_arch = "riscv64"))]
hypervisor,
stop_on_boot,
load_payload_handle,
@@ -803,6 +809,7 @@ impl Vm {
) -> Result<Self> {
trace_scoped!("Vm::new");
#[cfg(not(target_arch = "riscv64"))]
let timestamp = Instant::now();
#[cfg(feature = "tdx")]
@@ -873,6 +880,7 @@ impl Vm {
seccomp_action,
hypervisor,
activate_evt,
#[cfg(not(target_arch = "riscv64"))]
timestamp,
console_info,
console_resize_pipe,
@@ -943,14 +951,16 @@ impl Vm {
pub fn generate_cmdline(
payload: &PayloadConfig,
#[cfg(target_arch = "aarch64")] device_manager: &Arc<Mutex<DeviceManager>>,
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] device_manager: &Arc<
Mutex<DeviceManager>,
>,
) -> Result<Cmdline> {
let mut cmdline = Cmdline::new(arch::CMDLINE_MAX_SIZE).map_err(Error::CmdLineCreate)?;
if let Some(s) = payload.cmdline.as_ref() {
cmdline.insert_str(s).map_err(Error::CmdLineInsertStr)?;
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
for entry in device_manager.lock().unwrap().cmdline_additions() {
cmdline.insert_str(entry).map_err(Error::CmdLineInsertStr)?;
}
@@ -1005,6 +1015,47 @@ impl Vm {
Ok(EntryPoint { entry_addr })
}
#[cfg(target_arch = "riscv64")]
fn load_kernel(
firmware: Option<File>,
kernel: Option<File>,
memory_manager: Arc<Mutex<MemoryManager>>,
) -> Result<EntryPoint> {
let guest_memory = memory_manager.lock().as_ref().unwrap().guest_memory();
let mem = guest_memory.memory();
let alignment = 0x20_0000;
let aligned_kernel_addr = arch::layout::KERNEL_START.0 + (alignment - 1) & !(alignment - 1);
let entry_addr = match (firmware, kernel) {
(None, Some(mut kernel)) => {
match linux_loader::loader::pe::PE::load(
mem.deref(),
Some(GuestAddress(aligned_kernel_addr)),
&mut kernel,
None,
) {
Ok(entry_addr) => entry_addr.kernel_load,
// Try to load the binary as kernel PE file at first.
// If failed, retry to load it as UEFI binary.
// As the UEFI binary is formatless, it must be the last option to try.
Err(linux_loader::loader::Error::Pe(InvalidImageMagicNumber)) => {
// TODO: UEFI for riscv64 is scheduled to next stage.
unimplemented!()
}
Err(e) => {
return Err(Error::KernelLoad(e));
}
}
}
(Some(_firmware), None) => {
// TODO: UEFI for riscv64 is scheduled to next stage.
unimplemented!()
}
_ => return Err(Error::InvalidPayload),
};
Ok(EntryPoint { entry_addr })
}
#[cfg(feature = "igvm")]
fn load_igvm(
igvm: File,
@@ -1133,7 +1184,7 @@ impl Vm {
}
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
fn load_payload(
payload: &PayloadConfig,
memory_manager: Arc<Mutex<MemoryManager>>,
@@ -1351,6 +1402,72 @@ impl Vm {
Ok(())
}
#[cfg(target_arch = "riscv64")]
fn configure_system(&mut self) -> Result<()> {
let cmdline = Self::generate_cmdline(
self.config.lock().unwrap().payload.as_ref().unwrap(),
&self.device_manager,
)?;
let num_vcpu = self.cpu_manager.lock().unwrap().vcpus().len();
let mem = self.memory_manager.lock().unwrap().boot_guest_memory();
let mut pci_space_info: Vec<PciSpaceInfo> = Vec::new();
let initramfs_config = match self.initramfs {
Some(_) => Some(self.load_initramfs(&mem)?),
None => None,
};
let device_info = &self
.device_manager
.lock()
.unwrap()
.get_device_info()
.clone();
for pci_segment in self.device_manager.lock().unwrap().pci_segments().iter() {
let pci_space = PciSpaceInfo {
pci_segment_id: pci_segment.id,
mmio_config_address: pci_segment.mmio_config_address,
pci_device_space_start: pci_segment.start_of_mem64_area,
pci_device_space_size: pci_segment.end_of_mem64_area
- pci_segment.start_of_mem64_area
+ 1,
};
pci_space_info.push(pci_space);
}
// TODO: IOMMU for riscv64 is not yet support in kernel.
let vaia = self
.device_manager
.lock()
.unwrap()
.get_interrupt_controller()
.unwrap()
.lock()
.unwrap()
.get_vaia()
.map_err(|_| {
Error::ConfigureSystem(arch::Error::PlatformSpecific(
arch::riscv64::Error::SetupAia,
))
})?;
// TODO: PMU support for riscv64 is scheduled to next stage.
arch::configure_system(
&mem,
cmdline.as_cstring().unwrap().to_str().unwrap(),
num_vcpu as u32,
device_info,
&initramfs_config,
&pci_space_info,
&vaia,
)
.map_err(Error::ConfigureSystem)?;
Ok(())
}
pub fn console_resize_pipe(&self) -> Option<Arc<File>> {
self.device_manager.lock().unwrap().console_resize_pipe()
}
@@ -2017,6 +2134,7 @@ impl Vm {
// In case of TDX being used, this is a no-op since the tables will be
// created and passed when populating the HOB.
#[cfg(not(target_arch = "riscv64"))]
fn create_acpi_tables(&self) -> Option<GuestAddress> {
#[cfg(feature = "tdx")]
if self.config.lock().unwrap().is_tdx_enabled() {
@@ -2118,6 +2236,7 @@ impl Vm {
#[cfg(target_arch = "aarch64")]
let rsdp_addr = self.create_acpi_tables();
#[cfg(not(target_arch = "riscv64"))]
// Configure shared state based on loaded kernel
entry_point
.map(|entry_point| {
@@ -2127,6 +2246,9 @@ impl Vm {
})
.transpose()?;
#[cfg(target_arch = "riscv64")]
self.configure_system().unwrap();
#[cfg(target_arch = "x86_64")]
// Note: For x86, always call this function before invoking start boot vcpus.
// Otherwise guest would fail to boot because we haven't created the
@@ -2327,6 +2449,11 @@ impl Vm {
.map_err(Error::PowerButton)
}
#[cfg(target_arch = "riscv64")]
pub fn power_button(&self) -> Result<()> {
unimplemented!()
}
pub fn memory_manager_data(&self) -> MemoryManagerSnapshotData {
self.memory_manager.lock().unwrap().snapshot_data()
}

View File

@@ -486,7 +486,8 @@ pub struct PmemConfig {
impl ApplyLandlock for PmemConfig {
fn apply_landlock(&self, landlock: &mut Landlock) -> LandlockResult<()> {
landlock.add_rule_with_access(self.file.to_path_buf(), "rw")?;
let access = if self.discard_writes { "r" } else { "rw" };
landlock.add_rule_with_access(self.file.to_path_buf(), access)?;
Ok(())
}
}