Compare commits

..

292 Commits
v39.0 ... v41.0

Author SHA1 Message Date
Rob Bradford
ea3e2ff625 build: Release v41.0
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-08-15 16:50:09 +00:00
ihciah
3320015793 virtio-devices: net: reduce vec allocations for iovec conversion
Signed-off-by: ihciah <ihciah@gmail.com>
2024-08-15 11:56:46 +00:00
dependabot[bot]
9113544e21 build: Bump anstyle-wincon from 3.0.3 to 3.0.4
Bumps [anstyle-wincon](https://github.com/rust-cli/anstyle) from 3.0.3 to 3.0.4.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.3...anstyle-wincon-v3.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 07:02:09 +00:00
dependabot[bot]
8c526891ac build: Bump cc from 1.1.10 to 1.1.11 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.1.10 to 1.1.11.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.10...cc-v1.1.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 00:33:32 +00:00
Wei Liu
78a30012fb pci: validate index before accessing MSI-X arrays
The index is derived from the access offset, so it is controlled by the
guest. Check it before accessing internal data structures.

Since Rust enforces strict bound check even in release builds, the VMM
process will crash if the guest misbehaves. There is no security issue
since the guest can only DoS itself.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-08-14 08:01:25 +00:00
dependabot[bot]
c5c751c478 build: Bump cc from 1.1.7 to 1.1.10 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.1.7 to 1.1.10.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.7...cc-v1.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-14 00:49:14 +00:00
dependabot[bot]
f92cce888b build: Bump signal-hook-registry from 1.4.1 to 1.4.2
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.1 to 1.4.2.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.1...registry-v1.4.2)

---
updated-dependencies:
- dependency-name: signal-hook-registry
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 23:49:52 +00:00
Nuno Das Neves
00b4d97826 vmm: Replace hardcoded mshv IOCTL numbers in seccomp
Use the IOCTL numbers directly from mshv-ioctls instead of hardcoding
them in the seccomp filters.

Remove seccomp rules for unused ioctls:
MSHV_GET_VERSION_INFO,
MSHV_ASSERT_INTERRUPT.

Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
2024-08-13 18:52:46 +00:00
Jinank Jain
3fe7d6d904 hypervisor: mshv: Disable previous GHCB page before setting new one
CVM guests can configure GHCB page multiple times during it's
lifetime depending on it's requirement. For example a Linux CVM guest
configures a different GHCB page during compressed kernel boot and sets
up a new one after decompressing the kernel. As a cleanup step, VMM
should unset the previous GHCB page before registering a new one for
a particular vcpu thread.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-08-13 16:59:31 +00:00
Alyssa Ross
02f146fef8 hypervisor: kvm: aarch64: fix get_device_attr() UB
DeviceFd::get_device_attr should be marked as unsafe, because it
allows writing to an arbitrary address.  I have opened a kvm-ioctls
PR[1] to fix this.  The hypervisor crate was using the function
unsafely by passing it addresses of immutable variables.  I noticed
this because an optimisation change[2] in Rust 1.80.0 caused the
kvm::aarch64::gic::tests::test_get_set_icc_regs test to start failing
when built in release mode.

To fix this, I've broken up the _access functions into _set and _get
variants, with the _get variant using a pointer to a mutable variable.
This has the side effect of making these functions a bit nicer to use,
because the caller now has no need to use references at all, for
either getting or setting.

[1]: https://github.com/rust-vmm/kvm-ioctls/pull/273
[2]: d2d24e395a

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2024-08-13 16:16:11 +00:00
dependabot[bot]
36cdd67b9c build: Bump bitflags from 2.5.0 to 2.6.0
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.5.0 to 2.6.0.
- [Release notes](https://github.com/bitflags/bitflags/releases)
- [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bitflags/bitflags/compare/2.5.0...2.6.0)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 00:21:45 +00:00
dependabot[bot]
92b12ce2f4 build: Bump anstream from 0.6.14 to 0.6.15 in /fuzz
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.14 to 0.6.15.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.14...anstream-v0.6.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 23:51:09 +00:00
Alyssa Ross
cbb588c380 virtio-devices: allow vsock to call fcntl in debug
This fixes the vsock::device::tests::test_virtio_device test with Rust
1.80.0 or later, where this check was introduced.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2024-08-12 20:13:13 +00:00
Wei Liu
1c7997c5c3 hypervisor: x86: emulate MOVSQ
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-08-10 23:49:09 +00:00
dependabot[bot]
fee769bed4 build: Bump libc from 0.2.153 to 0.2.155
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.153 to 0.2.155.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.153...0.2.155)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-10 00:43:15 +00:00
dependabot[bot]
6b2c2c938a build: Bump indexmap from 2.2.6 to 2.3.0 in /fuzz
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.2.6 to 2.3.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.2.6...2.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-10 00:20:55 +00:00
Muminul Islam
1e967697c2 vmm: pass AccessPlatform implementation for SEV-SNP guest
Passing AccessPlatform trait to virtio-device for requesting
restricting page access during IO for SEV-SNP guest.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-08-09 17:40:13 +00:00
Muminul Islam
959ea7115f vmm: implement AccessPlatform for SEV-SNP proxy struct
Implement AccessPlatform for SEV-SNP guest to access
restricted page using IO. VMM calls MSHV api to get access
of the pages, MSHV requests guest to release the access.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-08-09 17:40:13 +00:00
Muminul Islam
398e9338a7 vmm: add a proxy struct for SEV-SNP guest
Add a structure to hold the reference of the Vm trait
from Hypervisor crate to access of restricted page
from SEV-SNP guest.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-08-09 17:40:13 +00:00
Muminul Islam
5c4b5c0e40 hypervisor: mshv: add definition to get access pages
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-08-09 17:40:13 +00:00
dependabot[bot]
f9bd2aaf9f build: Bump errno from 0.3.8 to 0.3.9
Bumps [errno](https://github.com/lambda-fairy/rust-errno) from 0.3.8 to 0.3.9.
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-09 07:38:12 +00:00
dependabot[bot]
f126288159 build: Bump anstyle-wincon from 3.0.3 to 3.0.4 in /fuzz
Bumps [anstyle-wincon](https://github.com/rust-cli/anstyle) from 3.0.3 to 3.0.4.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.3...anstyle-wincon-v3.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-09 00:05:18 +00:00
dependabot[bot]
9f9a4e657f build: Bump async-channel from 2.2.0 to 2.3.0
Bumps [async-channel](https://github.com/smol-rs/async-channel) from 2.2.0 to 2.3.0.
- [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.2.0...v2.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 00:44:32 +00:00
dependabot[bot]
3097d78c6e build: Bump jobserver from 0.1.31 to 0.1.32 in /fuzz
Bumps [jobserver](https://github.com/rust-lang/jobserver-rs) from 0.1.31 to 0.1.32.
- [Commits](https://github.com/rust-lang/jobserver-rs/compare/0.1.31...0.1.32)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 00:34:17 +00:00
dependabot[bot]
7c2a252c02 build: Bump toml_datetime from 0.6.6 to 0.6.8 in /fuzz
Bumps [toml_datetime](https://github.com/toml-rs/toml) from 0.6.6 to 0.6.8.
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.6.6...toml_datetime-v0.6.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 00:06:19 +00:00
dependabot[bot]
a87b25a962 build: Bump bumpalo from 3.15.4 to 3.16.0
Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.15.4 to 3.16.0.
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.15.4...3.16.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 23:55:41 +00:00
Wei Liu
24ed063dbe github: add build and clippy tests for pvmemcontrol
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-08-06 18:39:30 +00:00
dependabot[bot]
fbac81843f build: Bump clap from 4.5.9 to 4.5.13 in /fuzz
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.9...v4.5.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 08:08:06 +00:00
dependabot[bot]
610a2234dc build: Bump ppv-lite86 from 0.2.17 to 0.2.20
Bumps [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) from 0.2.17 to 0.2.20.
- [Commits](https://github.com/cryptocorrosion/cryptocorrosion/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 23:49:43 +00:00
Yuanchu Xie
5f18ac3bc0 devices: Add pvmemcontrol device
Pvmemcontrol provides a way for the guest to control its physical memory
properties, and enables optimizations and security features. For
example, the guest can provide information to the host where parts of a
hugepage may be unbacked, or sensitive data may not be swapped out, etc.

Pvmemcontrol allows guests to manipulate its gPTE entries in the SLAT,
and also some other properties of the memory map the back's host memory.
This is achieved by using the KVM_CAP_SYNC_MMU capability. When this
capability is available, the changes in the backing of the memory region
on the host are automatically reflected into the guest. For example, an
mmap() or madvise() that affects the region will be made visible
immediately.

There are two components of the implementation: the guest Linux driver
and Virtual Machine Monitor (VMM) device. A guest-allocated shared
buffer is negotiated per-cpu through a few PCI MMIO registers, the VMM
device assigns a unique command for each per-cpu buffer. The guest
writes its pvmemcontrol request in the per-cpu buffer, then writes the
corresponding command into the command register, calling into the VMM
device to perform the pvmemcontrol request.

The synchronous per-cpu shared buffer approach avoids the kick and busy
waiting that the guest would have to do with virtio virtqueue transport.

The Cloud Hypervisor component can be enabled with --pvmemcontrol.

Co-developed-by: Stanko Novakovic <stanko@google.com>
Co-developed-by: Pasha Tatashin <tatashin@google.com>
Signed-off-by: Yuanchu Xie <yuanchu@google.com>
2024-08-05 22:41:56 +00:00
Yuanchu Xie
4bf2d4f7dd pci: Remove BusDevice requirement from PciDevice
The BusDevice requirement is not needed, only Send is required.

Signed-off-by: Yuanchu Xie <yuanchu@google.com>
2024-08-05 22:41:56 +00:00
Yuanchu Xie
954f3dd057 vm-device: generalize BusDevice to use a shared reference
BusDevice trait functions currently holds a mutable reference to self,
and exclusive access is guaranteed by taking a Mutex when dispatched by
the Bus object. However, this prevents individual devices from serving
accesses that do not require an mutable reference or is better served
with different synchronization primitives. We switch Bus to dispatch via
BusDeviceSync, which holds a shared reference, and delegate locking to
the BusDeviceSync trait implementation for Mutex<BusDevice>.

Other changes are made to make use of the dyn BusDeviceSync
trait object.

Signed-off-by: Yuanchu Xie <yuanchu@google.com>
2024-08-05 22:41:56 +00:00
Praveen K Paladugu
026e2c6aa8 docs: Minor doc update
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-08-05 17:46:30 +00:00
Praveen K Paladugu
be9f57dcf9 vmm: Add landlock elements to openapi spec
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-08-05 17:46:30 +00:00
Praveen K Paladugu
bd180bc3eb main: rename landlock_config to landlock_rules
To keep the naming consistent, rename all uses of landlock_config
to landlock_rules.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-08-05 17:46:30 +00:00
Praveen K Paladugu
b9f086bcb3 tests: drop landlock parameter while starting dest
After moving landlock config to VMConfig, there is no need to start
destination VM with landlock cmdline options in
test_live_migration_with_landlock test.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-08-05 17:46:30 +00:00
Praveen K Paladugu
d2f0e8aebb Revert "vmm: make landlock configs VMM-level config"
This reverts commit 94929889ac.
This revert moves landlock config back to VMConfig.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-08-05 17:46:30 +00:00
dependabot[bot]
513973873c build: Bump igvm from 0.3.1 to 0.3.3
Bumps [igvm](https://github.com/microsoft/igvm) from 0.3.1 to 0.3.3.
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](https://github.com/microsoft/igvm/compare/igvm-v0.3.1...igvm-v0.3.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-02 23:56:38 +00:00
dependabot[bot]
4c52fa344e build: Bump anstyle-query from 1.1.0 to 1.1.1 in /fuzz
Bumps [anstyle-query](https://github.com/rust-cli/anstyle) from 1.1.0 to 1.1.1.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.0...anstyle-query-v1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-02 23:48:15 +00:00
Songqian Li
e18d32bac2 performance-metrics: add restore latency performance metric
This patch calculates the recovery latency from the start of
recovery program to the end of restore.

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-08-02 08:29:03 +00:00
dependabot[bot]
59185050d5 build: Bump colorchoice from 1.0.1 to 1.0.2 in /fuzz
Bumps [colorchoice](https://github.com/rust-cli/anstyle) from 1.0.1 to 1.0.2.
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.1...colorchoice-v1.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-02 00:44:49 +00:00
dependabot[bot]
dc72ef42dc build: Bump serde_with from 3.7.0 to 3.9.0
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.7.0 to 3.9.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.7.0...v3.9.0)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-02 00:35:54 +00:00
dependabot[bot]
68bb32a3e7 build: Bump cc from 1.0.104 to 1.1.7 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.104 to 1.1.7.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.104...cc-v1.1.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-01 12:27:25 +00:00
dependabot[bot]
0f89387475 build: Bump zerocopy from 0.7.32 to 0.7.35
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.32 to 0.7.35.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-01 00:34:37 +00:00
Wei Liu
f5b2eb5c76 virtio-devices: vsock: drop a useless line
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-31 16:36:10 +00:00
Wei Liu
82ac114b8a virtio-devices: vsock: handle short read in muxer
Use read_exact to make sure we really get the minimum number of bytes.

Fixes: #6621
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-31 16:36:10 +00:00
dependabot[bot]
2ffd5df018 build: Bump clap_lex from 0.7.1 to 0.7.2 in /fuzz
Bumps [clap_lex](https://github.com/clap-rs/clap) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.1...clap_lex-v0.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-31 07:30:47 +00:00
dependabot[bot]
006a12d911 build: Bump colorchoice from 1.0.0 to 1.0.2
Bumps [colorchoice](https://github.com/rust-cli/anstyle) from 1.0.0 to 1.0.2.
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.0...colorchoice-v1.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-31 00:22:37 +00:00
dependabot[bot]
bb55976454 build: Bump num_enum from 0.7.2 to 0.7.3
Bumps [num_enum](https://github.com/illicitonion/num_enum) from 0.7.2 to 0.7.3.
- [Commits](https://github.com/illicitonion/num_enum/compare/0.7.2...0.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-30 08:24:29 +00:00
dependabot[bot]
a15e041138 build: Bump anstyle from 1.0.7 to 1.0.8 in /fuzz
Bumps [anstyle](https://github.com/rust-cli/anstyle) from 1.0.7 to 1.0.8.
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.7...v1.0.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-30 00:44:06 +00:00
dependabot[bot]
0fa96402b8 build: Bump paste from 1.0.14 to 1.0.15
Bumps [paste](https://github.com/dtolnay/paste) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/dtolnay/paste/releases)
- [Commits](https://github.com/dtolnay/paste/compare/1.0.14...1.0.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 16:25:22 +00:00
dependabot[bot]
bc0ef1d8ba build: Bump is_terminal_polyfill from 1.70.0 to 1.70.1 in /fuzz
Bumps [is_terminal_polyfill](https://github.com/polyfill-rs/is_terminal_polyfill) from 1.70.0 to 1.70.1.
- [Changelog](https://github.com/polyfill-rs/is_terminal_polyfill/blob/main-v1.70/CHANGELOG.md)
- [Commits](https://github.com/polyfill-rs/is_terminal_polyfill/compare/v1.70.0...v1.70.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-27 00:41:27 +00:00
dependabot[bot]
86153225cf build: Bump darling from 0.20.8 to 0.20.10 in /fuzz
Bumps [darling](https://github.com/TedDriggs/darling) from 0.20.8 to 0.20.10.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/compare/v0.20.8...v0.20.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-26 08:31:02 +00:00
dependabot[bot]
ddc3f194aa build: Bump anyhow from 1.0.81 to 1.0.86
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.86.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.86)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-26 00:25:08 +00:00
dependabot[bot]
c6cc3d3ba9 build: Bump utf8parse from 0.2.1 to 0.2.2 in /fuzz
Bumps [utf8parse](https://github.com/alacritty/vte) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/alacritty/vte/releases)
- [Changelog](https://github.com/alacritty/vte/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alacritty/vte/compare/utf8parse_v0.2.1...utf8parse_v0.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-25 12:19:27 +00:00
dependabot[bot]
0fbb3e2c2c build: Bump serde_json from 1.0.115 to 1.0.120
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.120.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.120)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-25 00:28:26 +00:00
Jinank Jain
330e1aac36 hypervisor: mshv: Clear SW_EXIT_INFO1 in case of no error
There were some scenarios where we are not clearing SW_EXIT_INFO1 to
indicate that there were no error while handling the GHCB exit.
Recently, new Linux guests got stricter with checking the value of
SW_EXIT_INFO1 after coming back from VMGEXIT and started crashing. Fix
this behavior by clearing out SW_EXIT_INFO1 in case of no error.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-07-24 01:31:10 +00:00
dependabot[bot]
5fddf76a3b build: Bump remain from 0.2.13 to 0.2.14
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.13 to 0.2.14.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.13...0.2.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-24 00:28:08 +00:00
dependabot[bot]
b50dfb3538 build: Bump syn from 2.0.70 to 2.0.72 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.70 to 2.0.72.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.70...2.0.72)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-24 00:19:04 +00:00
dependabot[bot]
502995746a build: Bump anstream from 0.6.13 to 0.6.14
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.13 to 0.6.14.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.13...anstream-v0.6.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-23 21:07:26 +00:00
Wei Liu
8aa2d7ab2a devices: use byte strings directly
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
Wei Liu
bd8c28d341 vmm: use inspect_err instead of map_err
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
Wei Liu
422906a0c7 performance-metrics: use inspect_err instead of map_err
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
Wei Liu
b7512263be virtio-devices: iommu: use inspect_err instead of map_err
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
Wei Liu
7e749c0390 block: use inspect_err instead of map_err
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
Wei Liu
61a5bae25c option_parser: use an array directly to simplify code
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-23 21:07:17 +00:00
wuxinyue
a2438700e4 virtio-devices: support event idx for virtio-blk
Support event idx feature for virtio-blk device.
This feature could improve disk IO performance by suppressing
notifications from guest to host and interrupts from host to
guest, which has been already supported in virtio-net and
vhost-user devices.

To achieve this, virtqueue's event-idx-related API is
leveraged for avail_event field update and needs_notification
check.

Fixes: #6580
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
2024-07-23 14:16:34 +00:00
dependabot[bot]
bb4af57219 build: Bump windows-targets from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows-targets](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-23 00:21:58 +00:00
Wei Liu
824e83ab0d hypervisor: x86: emulate STOS
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-22 15:07:59 +00:00
dependabot[bot]
29675cfe68 build: Bump piper from 0.2.1 to 0.2.3
Bumps [piper](https://github.com/smol-rs/piper) from 0.2.1 to 0.2.3.
- [Release notes](https://github.com/smol-rs/piper/releases)
- [Changelog](https://github.com/smol-rs/piper/blob/main/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/piper/compare/v0.2.1...v0.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-20 00:48:21 +00:00
dependabot[bot]
43632f255b build: Bump clap from 4.5.7 to 4.5.9 in /fuzz
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.7 to 4.5.9.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.7...v4.5.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-19 23:51:34 +00:00
dependabot[bot]
a1941ad10b build: Bump regex from 1.10.4 to 1.10.5
Bumps [regex](https://github.com/rust-lang/regex) from 1.10.4 to 1.10.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.4...1.10.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-19 16:50:49 +00:00
dependabot[bot]
70db454b90 build: Bump windows_i686_msvc from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows_i686_msvc](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-19 02:49:59 +00:00
dependabot[bot]
7b3ffd89a5 build: Bump windows_i686_gnu from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows_i686_gnu](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-18 00:03:20 +00:00
Jinank Jain
c1f18fa634 arch: x86_64: Don't expose TSC deadline timer for MSHV guests
HV APIC(i.e., synthetic APIC controller exposed by Microsoft Hypervisor)
does not support one-shot operation using a TSC deadline value. Due to
which we see the following backtrace inside the guest when running with
hypervisor-fw/OVMF:

[    0.560765] unchecked MSR access error: WRMSR to 0x832 (tried to
write 0x00000000000400ec) at rIP: 0xffffffff8f473594
(native_write_msr+0x4/0x30)
[    0.560765] Call Trace:
[    0.560765]  ? native_apic_msr_write+0x2b/0x30
[    0.560765]  __setup_APIC_LVTT+0xbc/0xe0
[    0.560765]  lapic_timer_set_oneshot+0x27/0x30
[    0.560765]  clockevents_switch_state+0xaf/0xf0
[    0.560765]  tick_setup_periodic+0x47/0x90
[    0.560765]  tick_setup_device.isra.0+0x7c/0x110
[    0.560765]  tick_check_new_device+0xce/0xf0
[    0.560765]  clockevents_register_device+0x82/0x170
[    0.560765]  clockevents_config_and_register+0x2f/0x40
[    0.560765]  setup_APIC_timer+0xe1/0xf0
[    0.560765]  setup_boot_APIC_clock+0x5f/0x66
[    0.560765]  native_smp_prepare_cpus+0x1d6/0x286
[    0.560765]  kernel_init_freeable+0xcf/0x255
[    0.560765]  ? rest_init+0xb0/0xb0
[    0.560765]  kernel_init+0xe/0x110
[    0.560765]  ret_from_fork+0x22/0x40

Also, if this feature is exposed guest would not finish booting and get
stuck right before unpacking the root filesystem.

Fixes: 06e8d1c40 ("hypervisor: mshv: fix topology for Intel HW on MSHV")
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-07-17 17:10:08 +00:00
Bo Chen
efb92d409f docs: performance_metrics: Add example section with sample numbers
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-07-17 15:25:03 +00:00
Bo Chen
e4aa3617c7 docs: performance_metrics: Wrap line at 80 characters
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-07-17 15:25:03 +00:00
Songqian Li
d7e8cd8258 docs: improve performance metrics documentation
Add a performance metrics list and the definition of output format.

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-07-17 15:25:03 +00:00
dependabot[bot]
8803e4a2e7 build: Bump thiserror from 1.0.61 to 1.0.62
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.61 to 1.0.62.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.61...1.0.62)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-17 08:00:35 +00:00
dependabot[bot]
d2a01f7cec build: Bump uuid from 1.8.0 to 1.10.0 in /fuzz
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.8.0 to 1.10.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.8.0...1.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-17 00:12:50 +00:00
dependabot[bot]
dec4a82058 build: Bump log from 0.4.21 to 0.4.22
Bumps [log](https://github.com/rust-lang/log) from 0.4.21 to 0.4.22.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-16 06:20:32 +00:00
dependabot[bot]
5fc143205c build: Bump windows_aarch64_msvc from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows_aarch64_msvc](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-16 00:29:11 +00:00
Jinank Jain
b73d94f969 hypervisor: mshv: Refactor x86 emulator into different module
This is a preparatory work to make space for ARM64 emulator.
There is no functional change in this commit, just moving code from one
file to another.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-07-15 23:05:11 +00:00
Jinank Jain
ead4f767ff hypervisor: mshv: Restrict dependency to x86
iced_x86 is only available on x86 architecture.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-07-15 23:05:11 +00:00
Changyuan Lyu
bc6acb842f block: fix status value size
As per VirtIO spec 1.2 section 5.2.6, the `status` field is a byte, not
u32. cloud-hypervisor writes an `u32` to guest memory, which
accidentally zeros out the following 3 bytes, and may corrupt guest OS
internal state.

Signed-off-by: Changyuan Lyu <changyuanl@google.com>
2024-07-14 19:23:06 +00:00
dependabot[bot]
d89f1f4f21 build: Bump serde_with from 3.8.1 to 3.8.3 in /fuzz
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.8.1 to 3.8.3.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.8.1...v3.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-13 00:23:33 +00:00
dependabot[bot]
dc90744ec3 build: Bump darling from 0.20.9 to 0.20.10
Bumps [darling](https://github.com/TedDriggs/darling) from 0.20.9 to 0.20.10.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/commits/v0.20.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-12 23:46:59 +00:00
Wei Liu
18340d9761 hypervisor: mshv: fine-grained control over translation flags
The assertion that only code emulation requires GVA to GPA translation
is wrong.

Allow the caller of `translate` to pass in permission flags directly.

Provide a new method `read_memory_flags` so that we can add the EXECUTE
permission flag where necessary.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-12 16:12:33 +00:00
Wei Liu
cfaa192eb4 hypervisor: emulator: drop the unused gva_to_gpa hook
That function is too limiting. It doesn't consider page permissions. It
is not used, so just drop it.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-12 16:12:33 +00:00
dependabot[bot]
c67f799717 build: Bump windows_x86_64_msvc from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows_x86_64_msvc](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-12 00:02:26 +00:00
dependabot[bot]
b47efc3bc2 build: Bump enumflags2 from 0.7.9 to 0.7.10
Bumps [enumflags2](https://github.com/meithecatte/enumflags2) from 0.7.9 to 0.7.10.
- [Release notes](https://github.com/meithecatte/enumflags2/releases)
- [Commits](https://github.com/meithecatte/enumflags2/compare/v0.7.9...v0.7.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-11 23:55:37 +00:00
dependabot[bot]
498f35a1ab build: Bump zerocopy from 0.7.34 to 0.7.35 in /fuzz
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.34 to 0.7.35.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-11 00:52:33 +00:00
dependabot[bot]
2d61bc36ed build: Bump anstyle from 1.0.6 to 1.0.7
Bumps [anstyle](https://github.com/rust-cli/anstyle) from 1.0.6 to 1.0.7.
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.6...v1.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-10 23:53:26 +00:00
dependabot[bot]
46447962b8 build: Bump windows_i686_gnullvm from 0.52.5 to 0.52.6 in /fuzz
Bumps [windows_i686_gnullvm](https://github.com/microsoft/windows-rs) from 0.52.5 to 0.52.6.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-10 00:21:49 +00:00
dependabot[bot]
9a6bc025a7 build: Bump backtrace from 0.3.71 to 0.3.73
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.71 to 0.3.73.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.71...0.3.73)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-10 00:08:56 +00:00
Rob Bradford
de1abe0e30 vmm: Use Response::ok_or_abandon() in migration logic
The use of this method removes duplicated code yet provides clarity on
the logic.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-07-09 19:53:26 +00:00
Rob Bradford
e97cee99ef vm-migration: Introduce Response::ok_or_abandon()
This method will return the existing Response if the status is
successful (Status::Ok) otherwise issue a command to abandon the
migration and return the desired error.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-07-09 19:53:26 +00:00
Wei Liu
3103526153 build: update pnet crates
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-09 19:52:59 +00:00
dependabot[bot]
08ff89ba6e build: Bump zvariant from 4.1.1 to 4.1.2
Bumps [zvariant](https://github.com/dbus2/zbus) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zvariant-4.1.1...zvariant-4.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-09 00:34:10 +00:00
dependabot[bot]
514f36fb5a build: Bump syn from 2.0.68 to 2.0.70 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.68 to 2.0.70.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.68...2.0.70)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-09 00:00:14 +00:00
dependabot[bot]
fe3506976e build: Bump cc from 1.0.101 to 1.0.104 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.101 to 1.0.104.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.101...cc-v1.0.104)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-06 04:54:03 +00:00
Wei Liu
94929889ac vmm: make landlock configs VMM-level config
This requires stashing the config values in `struct Vmm`. The configs
should be validated before before creating the VMM thread. Refactor the
code and update documentation where necessary.

The place where the rules are applied remain the same.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
8452edfcc7 tests: Test live migration with Landlock
Add a test case to check Live Migration with Landlock support.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
466cc5e043 tests: Add disk_hotplug test with Landlock
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
034c674c4c tests: Add a basic Landlock test
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
b785e00317 docs: Add doc for Landlock feature
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
7f6731cd05 vmm: Limit the visibility of Landlock objects
Limit the visibility of objects and methods introduced by Landlock
implementation.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
457fd9ef96 vmm: enable landlock during live migration
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
eea45a2c78 vmm: Enable Landlock in restore path
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
11c17ca319 main: Enable landlock on main thread
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
249e362c70 vmm: Enable Landlock on vmm thread
Add file/dir paths from landlock-rules arguments to ruleset. Invoke
apply_landlock on VmConfig to apply config specific rules to ruleset.

Once done, any threads spawned by vmm thread will be automatically
sandboxed with the ruleset in vmm thread.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
b3e5738b40 vmm: Introduce ApplyLandlock trait
Introduce ApplyLandlock trait and add implementations to VmConfig
elements with PathBufs. This trait adds config specific rules to
landlock ruleset.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
1dd53c3d24 vmm: Enable Landlock on http-server thread
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
130c988380 vmm: Enable Landlock on signal-handler thread
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
8c76a3e4b5 vmm: Enable Landlock on event-monitor thread
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
af5a9677c8 vmm: Introduce Landlock module
This module introduces methods to apply Landlock LSM to cloud-hypervisor
threads.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
1d89f98edf vmm: Introduce landlock-rules cmdline param
Users can use this parameter to pass extra paths that 'vmm' and its
child threads can use at runtime. Hotplug is the primary usecase for
this parameter.

In order to hotplug devices that use local files: disks, memory zones,
pmem devices etc, users can use this option to pass the path/s that will
be used during hotplug while starting cloud-hypervisor. Doing this will
allow landlock to add required rules to grant access to these paths when
cloud-hypervisor process starts.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
287dbd4fc9 vmm: Introduce landlock cmdline parameter
Users can use this cmdline option to enable/disable Landlock based
sandboxing while running cloud-hypervisor.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Praveen K Paladugu
c50ea2c708 vmm: Add seccomp rules to allow landlock syscalls
landlock syscalls are required by event_monitor, signal_handler,
http-server and vmm threads. Rest of the threads are spawned by the vmm
thread and they automatically inherit the ruleset from the vmm thread.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-07-06 04:42:58 +00:00
Wei Liu
14b45e4d2e hypervisor: mshv: handle GPA intercept
We will start receiving GPA intercepts. For our use cases they are
handled the same way as UNMAPPED GPA intercepts.

Put in some logging to distinguish the two cases.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-04 18:45:01 +00:00
Wei Liu
519476e842 hypervisor: mshv: relax the requirement for instruction emulation
Previously we required the hypervisor to give us a valid instruction
stream. That worked well enough because we never hit any edge conditions
(such as when the instruction stream crosses page boundary).

Now that MSHV can deal with partial or empty instruction stream, we can
remove that requirement.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-04 18:45:01 +00:00
Wei Liu
5fec858130 hypervisor: mshv: implement fetching instructions in emulator
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-04 18:45:01 +00:00
Wei Liu
67f22b6aa4 hypervisor: mshv: fix GVA translation flags
Original we checked for R and W, but that code path never got executed.

It is now understood that we can only get here when we execute code. Fix
the permission flags.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-04 18:45:01 +00:00
Wei Liu
1eb4133034 hypervisor: x86: emulator: set IP properly for newly fetched stream
The default value of IP is zero. If the decoder's state not set
properly, then the guest state is going to be wrong.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-04 18:45:01 +00:00
dependabot[bot]
9f3bea3e3f build: Bump anstyle-parse from 0.2.3 to 0.2.4 in /fuzz
Bumps [anstyle-parse](https://github.com/rust-cli/anstyle) from 0.2.3 to 0.2.4.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.3...anstyle-parse-v0.2.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-03 21:54:50 +00:00
Alyssa Ross
e7c7a304e8 virtio-devices: fix UB getting tty size
TIOCGWINSZ modifies its argument, so it needs to mutably borrow it.
Unfortunately, ioctl()'s signature is not able to enforce this, and
the write happens in the kernel, so I don't think anything like miri,
valgrind, UBSan, etc. would have been able to catch this.

The UB passing an immutable reference caused resulted, for me, in
get_win_size() returning (0, 0) since LLVM commit
9a09c737a052 ("[BasicAA] Make isNotCapturedBeforeOrAt() check for
calls more precise (#69931)").

I've had a look through the other ioctl() calls in Cloud Hypervisor,
and I don't think any others have the same problem.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2024-07-03 21:26:04 +00:00
Bo Chen
b5cce0d371 build: Enable vfio and sgx worker
This reverts commit 7d84654a79.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-07-03 00:34:28 +00:00
Wei Liu
7c608f6380 hypervisor: x86: emulator: accept empty instruction stream input
The emulator should fetch from memory just fine.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-02 14:59:50 +00:00
Wei Liu
3ad8d24943 hypervisor: x86: emulator: fix a variable
Comparing RAX with RIP makes no logical sense other than RIP happens to
be the correct value. Use `target_rax` instead.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-02 14:59:50 +00:00
Wei Liu
56c6c02724 hypervisor: x86: emulator: test executing only one instruction
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-02 14:59:50 +00:00
Wei Liu
19b0ea842b hypervisor: x86: emulator: add the second instruction to test comment
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-07-02 14:59:50 +00:00
dependabot[bot]
16bd88b4b5 build: Bump cc from 1.0.99 to 1.0.101 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.99 to 1.0.101.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.99...cc-v1.0.101)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-28 00:28:40 +00:00
dependabot[bot]
09136c50b5 build: Bump syn from 2.0.66 to 2.0.68 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.66 to 2.0.68.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.66...2.0.68)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-27 17:44:00 +00:00
Nuno Das Neves
380b7d398c build: Bump openssl-src to 3.3.1
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
2024-06-25 18:55:52 +00:00
Nuno Das Neves
764959c9a8 build: Bump libz-sys to 1.1.18
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
2024-06-25 18:55:52 +00:00
Bo Chen
7d84654a79 build: Temporarily disable vfio and sgx worker
The corresponding bare-metal runner needs to be offline for
maintenance.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-06-25 17:40:20 +00:00
Julian Stecklina
246cb94dc5 build: Fix license string to comply with SPDX list
cargo-cyclonedx rejects the current license key in Cargo.toml, because
it doesn't comply with the SPDX standard:

  Package cloud-hypervisor has an invalid license expression (LICENSE-APACHE & LICENSE-BSD-3-Clause), using as named license: Invalid Lax SPDX expression: unknown term

Fix by using the names from the SPDX list:
https://spdx.github.io/license-list-data/

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2024-06-25 09:14:19 -07:00
dependabot[bot]
165c2c476f build: Bump proc-macro2 from 1.0.83 to 1.0.86 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.83 to 1.0.86.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.83...1.0.86)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-22 09:04:44 +00:00
dependabot[bot]
5e8f380698 build: Bump anyhow from 1.0.82 to 1.0.86 in /fuzz
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.86.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.86)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-21 16:45:25 +00:00
Rob Bradford
e9b2639757 build: Release v40.0
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-06-21 08:40:44 +00:00
dependabot[bot]
98d0aabb99 build: Bump clap from 4.5.4 to 4.5.7 in /fuzz
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.4 to 4.5.7.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.4...v4.5.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-20 00:36:09 +00:00
dependabot[bot]
d206586683 build: Bump crossbeam-utils from 0.8.19 to 0.8.20
Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.19 to 0.8.20.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.19...crossbeam-utils-0.8.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-19 00:32:27 +00:00
dependabot[bot]
19f2800d9e build: Bump clap_lex from 0.7.0 to 0.7.1 in /fuzz
Bumps [clap_lex](https://github.com/clap-rs/clap) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.0...clap_lex-v0.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-19 00:09:29 +00:00
Rob Bradford
08cf983d42 build: Fix Cargo.toml formatting
In 42e9632c53 a fix was made to address a
typo in the taplo configuration file. Fixing this typo indicated that
many Cargo.toml files were no longer adhering to the formatting rules.
Fix the formatting by running `taplo fmt`.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-06-18 16:19:12 +00:00
dependabot[bot]
243dc5918c build: Bump regex-automata from 0.4.6 to 0.4.7
Bumps [regex-automata](https://github.com/rust-lang/regex) from 0.4.6 to 0.4.7.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/regex-automata-0.4.6...regex-automata-0.4.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 14:26:39 +00:00
Songqian Li
544de7d000 tests: send SIGTERM to kill GuestCommand
Killing CLH by SIGKILL will cause inaccurate code coverage
information. This patch changes the signal to SIGTERM.

Fixes: #6507

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-06-18 08:03:09 +00:00
dependabot[bot]
796db588ea build: Bump serde from 1.0.202 to 1.0.203 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.202 to 1.0.203.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.202...v1.0.203)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 23:59:43 +00:00
dependabot[bot]
397c76dd20 build: Bump cc from 1.0.97 to 1.0.99
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.97 to 1.0.99.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.97...1.0.99)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-15 08:23:35 +00:00
Bo Chen
cdd3ff5e5a virtio-devices: vdpa: Don't restore on paused state
Since vdpa device does not support pause/resume [1], it does not make
sense to restore on paused state.

[1] 099cdd2af8

Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-06-15 07:32:58 +00:00
Bo Chen
6cb76abbf1 virtio-devices: vdpa: Don't error out on resume if not paused
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-06-15 07:32:58 +00:00
dependabot[bot]
3a5e5364b9 build: Bump cc from 1.0.98 to 1.0.99 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.98 to 1.0.99.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.98...1.0.99)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-15 00:37:02 +00:00
dependabot[bot]
f2b2d033f7 build: Bump colorchoice from 1.0.0 to 1.0.1 in /fuzz
Bumps [colorchoice](https://github.com/rust-cli/anstyle) from 1.0.0 to 1.0.1.
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.0...colorchoice-v1.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-14 00:52:33 +00:00
dependabot[bot]
c41461c9c2 build: Bump getrandom from 0.2.13 to 0.2.14
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.2.13 to 0.2.14.
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.13...v0.2.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 23:55:04 +00:00
Yu Li
9257322330 block: qcow: add unit test for max nesting depth
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2024-06-13 01:42:11 +00:00
Yu Li
220455caaf block: qcow: limit max nesting depth for backing file
Impose a limit on the maximum nesting of file formats that can open more
files. For example, a qcow2 file can have a backing file, which could be
another qcow2 file with a backing file (or even the same file as the
original), potentially causing unbounded recursion.

This commit is based on crosvm implementation:
eb1640e301

Fixes: #6472

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2024-06-13 01:42:11 +00:00
dependabot[bot]
c206c14318 build: Bump anstyle-query from 1.0.2 to 1.1.0 in /fuzz
Bumps [anstyle-query](https://github.com/rust-cli/anstyle) from 1.0.2 to 1.1.0.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.0.2...anstyle-query-v1.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 00:31:02 +00:00
dependabot[bot]
777757254b build: Bump async-io from 2.3.2 to 2.3.3
Bumps [async-io](https://github.com/smol-rs/async-io) from 2.3.2 to 2.3.3.
- [Release notes](https://github.com/smol-rs/async-io/releases)
- [Changelog](https://github.com/smol-rs/async-io/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-io/compare/v2.3.2...v2.3.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 00:22:10 +00:00
Wei Liu
9c42d98e6a devices: move LocalTime to test module
It is only used there.

Drop all its doc strings and pub annotations.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-06-12 16:59:20 +00:00
Wei Liu
254db7b96a vmm: fix documentation formatting
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-06-12 16:59:20 +00:00
Wei Liu
b3a73d6634 virtio-devices: fix documentation formatting
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-06-12 16:59:20 +00:00
Wei Liu
9cd214b0a1 rate_limiter: fix documentation indentation
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-06-12 16:59:20 +00:00
Praveen K Paladugu
9f969ee18d vmm: Use cloned fd to check if dev is a tty
While checking if the console device is a tty use the cloned fd instead
of libc::STDOUT_FILENO.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
c3fcddf830 vmm: Fix console dev handling in live migration
Console devices are created after vm_config is received and the created
devices are passed Vm during vm_receive_state.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
11d98fccac vmm: fix a typo in ioctl name
Rename TIOCGTPEER ioctl to it proper name:TIOCGPTPEER.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
a8fa2af64b vmm: dup serial fds to preserve them across reboots
During vm_shutdown or vm_snapshot, all the console devices will be
closed. When this happens stdout (FD #2) will also be closed as the
console device using these FD is closed. If the VM were to be started
later, FD#2 can be assigned to a different file. But
pre_create_console_devices looks for FD#2 while opening tty device,
which could point to any file.

To avoid this problem, the STDOUT FD is duplicated when being
assigned to a console device. Even if the console devices were to be
closed, the duplicated FD will be closed and FD#2 will continue to
point to STDOUT.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
dc723171a7 vmm: cleanup legacy console device management
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
52eebaf6b2 vmm: refactor DeviceManager to use console_info
While adding console devices, DeviceManager will now use the FDs in
console_info instead of creating them.

To reduce the size of this commit, I marked some variables are unused
with '_' prefix. All those variables are cleaned up in next commit.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
380ba564f4 vmm: populate console_info during vm actions
Use pre_create_console_devices method to create and populate console
device FDs into console_info in Vmm Object.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
385f9a9aa9 vmm: save console_resize_pipe info to Vmm
With this change all the information to manage console devices is now
available within Vmm Object.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
d784bf0c75 vmm: move listen_for_sigwinch_on_tty method
Move listen_for_sigwinch_on_tty to sigwinch_listener.rs module.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
Praveen K Paladugu
cf6115a73c vmm: Introduce console_devices module
Introduce ConsoleInfo struct. This struct will be used to store FDs of
console devices created in pre_create_console_devices and passed to
vm_boot.

Move set_raw_mode, create_pty methods to console_devices.rs to
consolidate console management methods into a single module.

Lastly, copy the logic to create and configure console devices into
pre_create_console_devices method.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-06-12 15:47:19 +00:00
dependabot[bot]
0991b881de build: Bump syn from 2.0.64 to 2.0.66 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.64 to 2.0.66.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.64...2.0.66)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 00:40:31 +00:00
dependabot[bot]
e048da6f73 build: Bump blocking from 1.5.1 to 1.6.1
Bumps [blocking](https://github.com/smol-rs/blocking) from 1.5.1 to 1.6.1.
- [Release notes](https://github.com/smol-rs/blocking/releases)
- [Changelog](https://github.com/smol-rs/blocking/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/blocking/compare/v1.5.1...v1.6.1)

---
updated-dependencies:
- dependency-name: blocking
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 00:32:18 +00:00
dependabot[bot]
6a08133efb build: Bump darling from 0.20.8 to 0.20.9
Bumps [darling](https://github.com/TedDriggs/darling) from 0.20.8 to 0.20.9.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-11 00:20:03 +00:00
Sean Banko
2e50f5769f arch: x86_64: fall back to host cpuid l1 cache info if omitted by kvm
If the KVM version is older than v6.6, KVM_GET_SUPPORTED_CPUID will omit
the L1 cache information in CPUID function 0x8000_0005. Fall back to
the host L1 cache information if it is omitted by KVM.

Signed-off-by: Sean Banko <sbanko@crusoe.ai>
2024-06-09 07:37:17 +00:00
Josh Soref
42e9632c53 misc: Fix spelling issues
Misspellings were identified by:
  https://github.com/marketplace/actions/check-spelling

* Initial corrections based on forbidden patterns from the action
* Additional corrections by Google Chrome auto-suggest
* Some manual corrections
* Adding markdown bullets to readme credits section

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2024-06-08 16:31:30 +00:00
dependabot[bot]
46c5fb5f2c build: Bump fastrand from 2.0.2 to 2.1.0
Bumps [fastrand](https://github.com/smol-rs/fastrand) from 2.0.2 to 2.1.0.
- [Release notes](https://github.com/smol-rs/fastrand/releases)
- [Changelog](https://github.com/smol-rs/fastrand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/fastrand/compare/v2.0.2...v2.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-08 00:15:59 +00:00
dependabot[bot]
81b41b55fd build: Bump rustix from 0.38.32 to 0.38.34
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.32 to 0.38.34.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.32...v0.38.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-07 00:13:21 +00:00
dependabot[bot]
112a971c56 build: Bump rustc-demangle from 0.1.23 to 0.1.24
Bumps [rustc-demangle](https://github.com/rust-lang/rustc-demangle) from 0.1.23 to 0.1.24.
- [Commits](https://github.com/rust-lang/rustc-demangle/compare/0.1.23...0.1.24)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-06 00:32:52 +00:00
Jinank Jain
9b87a7e699 misc: Update description in Cargo.toml to include MSHV
Since CloudHypervisor also supports running on top of Microsoft
Hypervisor (MSHV).

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-06-05 08:01:00 +00:00
Wei Liu
1bd8afeffa docs: remove executable permission from releases.md
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-06-04 16:13:53 -07:00
Jinank Jain
3414586995 arch: Change the default topology for x86 guests
Currently by default each core is allocated it's own socket. Basically
it is n socket 1 core 1 thread/core kind of a structure as witnessed
from within the guest.

CPU(s):                             8
On-line CPU(s) list:                0-7
Thread(s) per core:                 1
Core(s) per socket:                 1
Socket(s):                          8
NUMA node(s):                       1

This is not a good default topology because resources are distributed
across multiple sockets. For example, a Linux guest with multi socket
configuration will have to calibrate TSC per socket due to which it
might observe a higher amount of boot time than usual.

A better idea for default topology would be 1 socket n core 1
thread/core which ensure better resource locality.

After this change topology would change to:

CPU(s):                             8
On-line CPU(s) list:                0-7
Thread(s) per core:                 1
Core(s) per socket:                 8
Socket(s):                          1
NUMA node(s):                       1

Fixes: #6497

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-06-04 17:08:18 +00:00
Muminul Islam
06e8d1c40c hypervisor: mshv: fix topology for Intel HW on MSHV
Populating these cpuid with default values so that
CLH can patch with topology information. Otherwise it gets
skipped while setting some topology information.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-06-04 04:57:34 +00:00
dependabot[bot]
b70b8dfa4c build: Bump zvariant from 4.0.2 to 4.1.1
Bumps [zvariant](https://github.com/dbus2/zbus) from 4.0.2 to 4.1.1.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zvariant-4.0.2...zvariant-4.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 00:40:46 +00:00
dependabot[bot]
57e450a7a8 build: Bump anstream from 0.6.13 to 0.6.14 in /fuzz
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.13 to 0.6.14.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.13...anstream-v0.6.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 00:34:22 +00:00
dependabot[bot]
d82846c954 build: Bump range_map_vec from 0.1.0 to 0.2.0
Bumps [range_map_vec](https://github.com/microsoft/range_map_vec) from 0.1.0 to 0.2.0.
- [Commits](https://github.com/microsoft/range_map_vec/compare/v0.1.0...v0.2.0)

---
updated-dependencies:
- dependency-name: range_map_vec
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-01 00:53:03 +00:00
dependabot[bot]
714b61846c build: Bump crc-any from 2.4.4 to 2.5.0 in /fuzz
Bumps [crc-any](https://github.com/magiclen/crc-any) from 2.4.4 to 2.5.0.
- [Commits](https://github.com/magiclen/crc-any/compare/v2.4.4...v2.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-31 23:52:57 +00:00
Wei Liu
6bb3ad1b96 build: update IGVM crates
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-31 20:16:37 +00:00
dependabot[bot]
dd820d69ba build: Bump anstyle from 1.0.6 to 1.0.7 in /fuzz
Bumps [anstyle](https://github.com/rust-cli/anstyle) from 1.0.6 to 1.0.7.
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.6...v1.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-31 00:22:03 +00:00
Songqian Li
77c80f67ed tests: add snapshot_restore_pvpanic test
Add test_snapshot_restore_pvpanic to integration tests since pvpanic
 already supports snapshot.

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-05-30 17:07:12 +00:00
Rob Bradford
eb4dd90532 arch: x86_64: Avoid calling cpuid for setting LAPIC ID
Rather than calling cpuid and then updating the APIC ID field - use the
existing common CPUID data which already includes CPUID data for eax=1
(aka function = 1).  This removes the need to call cpuid per vCPU thread
created. This has a positive impact on boot time with multiple vCPUs as
the cpuid instruction is serialising.

Fixes: #5646

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-30 17:03:03 +00:00
dependabot[bot]
d3cd25566b build: Bump zerocopy from 0.7.32 to 0.7.34 in /fuzz
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.32 to 0.7.34.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.32...v0.7.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-30 00:34:05 +00:00
dependabot[bot]
925ab090af build: Bump getrandom from 0.2.14 to 0.2.15 in /fuzz
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.2.14 to 0.2.15.
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.14...v0.2.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-29 08:39:37 +00:00
Wei Liu
8caf29ec01 build: drop an invalid dependency in fuzz
The cloud-hypervisor package does not have a lib target, so it is
invalid. Cargo just ignores that line.

Dropping it removes a warning.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-29 09:35:32 +01:00
Alexandru Matei
091ce85473 main: update expand_fdtable comment
Updated the comment so it is sync with the code

Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
2024-05-28 14:50:40 +01:00
dependabot[bot]
133ac463c2 build: Bump serde_json from 1.0.115 to 1.0.117 in /fuzz
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.117.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.117)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 23:50:51 +00:00
Wei Liu
400837ff99 vmm: wrap a new fd in UnixListener in serial manager
The original code gave an owned fd to UnixListener. That made the same
fd wrapped into two owned files.

When the files were dropped, the same fd would be closed more than once.
A newly introduced check in Rust's stdlib caught that error.

A newly cloned fd should be given to UnixListener.

Fixes: #6485

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-27 19:24:28 +00:00
Wei Liu
a9e41c417a vmm: add a check to avoid wrapping -1 into an owned file
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-27 19:24:28 +00:00
Wei Liu
1845e63e7c devices: make IOAPIC log a bit more useful
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-27 19:24:28 +00:00
Alexandru Matei
f13d8f1412 main: fix high latency generated by file handle creation
Whenever the file descriptor table is full, Linux expands it by doubling
it's size.
The filesystem code that does this uses RCU synchronization to ensure
all pre-existing RCU read-side critical sections have completed. The
latency induced by this synchronization is a big part of the total time
required to restore a snapshot.

The kernel has an optimization in code, where it doesn't call
synchronize_rcu() if there is only one thread in the process. We can
take advantage of this optimization by expanding the descriptor table at
the application start, when it has only one thread.

This commit tries to expand the table to 4096 entries, this way we avoid
any expansion that could take place later.

Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
2024-05-25 01:09:10 +00:00
dependabot[bot]
bfe0106566 build: Bump proc-macro2 from 1.0.81 to 1.0.83 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.81 to 1.0.83.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.81...1.0.83)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-24 23:57:13 +00:00
dependabot[bot]
7c46e610e7 build: Bump linux-raw-sys from 0.4.13 to 0.4.14
Bumps [linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys) from 0.4.13 to 0.4.14.
- [Commits](https://github.com/sunfishcode/linux-raw-sys/compare/v0.4.13...v0.4.14)

---
updated-dependencies:
- dependency-name: linux-raw-sys
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-24 00:10:07 +00:00
dependabot[bot]
b13de200f5 build: Bump io-uring from 0.6.3 to 0.6.4 in /fuzz
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.6.3 to 0.6.4.
- [Commits](https://github.com/tokio-rs/io-uring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-23 23:58:38 +00:00
SamrutGadde
c3d69a9bac api_client: Updated error message for sending fds
Updated error message for the SocketSendFds error to be more
descriptive.

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
SamrutGadde
51a9f78625 hypervisor: aarch64: Use thiserror for errors
Updated error enums in hypervisor under aarch64 to use thiserror crate

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
SamrutGadde
89b429c768 devices: Use thiserror for errors
Updated error enums in device package to use thiserror crate

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
SamrutGadde
f25315d151 block: qcow: Use thiserror for errors
Added thiserror for missing files in the qcow module.

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
SamrutGadde
193c006669 arch: Use thiserror for errors
Added thiserror crate for missing files in the arch package

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
SamrutGadde
5d0d56f50b api_client: Use thiserror for errors
Added thiserror crate for Error enums to the api_client package

Signed-off-by: SamrutGadde <samrut.gadde@gmail.com>
2024-05-23 20:54:36 +00:00
Nuno Das Neves
30b6e412af hypervisor: mshv: Pin mshv crates to release tag v0.2.0
And bump vfio commit in Cargo.lock to align, since it should also point
to mshv v0.2.0.

Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
2024-05-23 17:37:49 +00:00
Jinank Jain
6c90623c8e hypervisor: mshv: Only perform SNP operation for x86 partition
SEV-SNP partitions are only supported on x86 architecture.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-05-23 15:18:00 +00:00
Jinank Jain
94fe22da62 hypervisor: mshv: Only set unimplemented MSR for x86 partition
This partition property is only supported for x86 partition. Thus,
reduce the scope of it.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-05-23 15:18:00 +00:00
Omer Faruk Bayram
036e7e3797 vmm: ch-remote: replace deprecated zbus macros with new equivalents
Fixes deprecation related warnings introduced in #6400.

Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
2024-05-23 12:20:06 +00:00
dependabot[bot]
5a811af099 build: Bump lock_api from 0.4.11 to 0.4.12 in /fuzz
Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.11 to 0.4.12.
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.11...lock_api-0.4.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-23 00:46:31 +00:00
dependabot[bot]
7ac2e56fa6 build: Bump ryu from 1.0.17 to 1.0.18
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.17 to 1.0.18.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.17...1.0.18)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 23:47:28 +00:00
dependabot[bot]
eb8f959361 build: Bump zbus from 3.15.2 to 4.1.2
Bumps [zbus](https://github.com/dbus2/zbus) from 3.15.2 to 4.1.2.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-3.15.2...zbus-4.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 15:51:56 +00:00
dependabot[bot]
27fd114cbf ---
updated-dependencies:
- dependency-name: num-traits
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 12:16:40 +00:00
dependabot[bot]
ba488f5c33 ---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 00:22:23 +00:00
Jinank Jain
af1f94e5b8 hypervisor: mshv: Reduce the scope of VMEXITs to x86_64
Certain VMEXITs can only happen for x86 guests, thus reduce the scope to
x86_64 at the compilation stage.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2024-05-21 16:16:29 +00:00
dependabot[bot]
22621df084 ---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 00:06:51 +00:00
dependabot[bot]
972b4bf248 ---
updated-dependencies:
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 23:55:32 +00:00
dependabot[bot]
f4aa3de335 build: Bump syn from 2.0.60 to 2.0.64 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.60 to 2.0.64.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.60...2.0.64)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-18 07:08:39 +00:00
dependabot[bot]
b2d25a582d build: Bump waker-fn from 1.1.1 to 1.2.0
Bumps [waker-fn](https://github.com/smol-rs/waker-fn) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/smol-rs/waker-fn/releases)
- [Changelog](https://github.com/smol-rs/waker-fn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/waker-fn/compare/v1.1.1...v1.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-17 23:46:56 +00:00
dependabot[bot]
a3262ad570 build: Bump async-signal from 0.2.5 to 0.2.6
Bumps [async-signal](https://github.com/smol-rs/async-signal) from 0.2.5 to 0.2.6.
- [Release notes](https://github.com/smol-rs/async-signal/releases)
- [Changelog](https://github.com/smol-rs/async-signal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-signal/compare/v0.2.5...v0.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-17 06:59:03 +00:00
dependabot[bot]
034283fc83 build: Bump remain from 0.2.13 to 0.2.14 in /fuzz
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.13 to 0.2.14.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.13...0.2.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-17 00:30:09 +00:00
Muminul Islam
860939d677 vmm: pause/resume VM during the VM events
For MSHV we always create frozen partition, so we
resume the VM during boot. Also during pause and resume
VM events we call hypervisor specific API.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-16 14:17:07 +00:00
Muminul Islam
a5a41bf797 hypervisor: always create a frozen partition
Create a partition frozen always, then unfreeze the partition
during boot phase or resume phase. We also freeze the
partition during pause event. Time is freeze during the
time between freeze and unfreeze.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-16 14:17:07 +00:00
Muminul Islam
aabfc9513e hypervisor: implement pause/resume API for MSHV
Implementing pause/Resume API for MSHV.
Here we set/reset the partition property(TIME_FREEZE)

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-16 14:17:07 +00:00
Muminul Islam
3fe9b87736 hypervisor: Add pause/resume definitions to VM trait
Add Pause/Resume functions for VM trait. For KVM it
will be empty implementations. For MSHV it needs to freeze
and unfreeze the partition.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-16 14:17:07 +00:00
dependabot[bot]
9e338d86f5 build: Bump serde from 1.0.201 to 1.0.202 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.202.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.202)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-16 00:12:16 +00:00
dependabot[bot]
5f9c6bc84f build: Bump autocfg from 1.2.0 to 1.3.0
Bumps [autocfg](https://github.com/cuviper/autocfg) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/cuviper/autocfg/compare/1.2.0...1.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-15 23:52:04 +00:00
Songqian Li
de38e4b777 tests: restart systemd daemon to reload systemd configuration
Currently, the watchdog configuration in systemd is reloaded by
reboot. We can cancel this reboot operation by restarting the
systemd daemon process.

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-05-15 11:17:42 +00:00
dependabot[bot]
6c4947e9ba build: Bump anstyle-wincon from 3.0.2 to 3.0.3
Bumps [anstyle-wincon](https://github.com/rust-cli/anstyle) from 3.0.2 to 3.0.3.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.2...anstyle-wincon-v3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-15 00:08:08 +00:00
dependabot[bot]
63df8599dc build: Bump serde from 1.0.198 to 1.0.201 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.198 to 1.0.201.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.198...v1.0.201)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 23:59:46 +00:00
Rob Bradford
b6003cb428 build: Use correct MSRV version for release workflow
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-14 14:45:10 +00:00
dependabot[bot]
340a51d08e build: Bump ryu from 1.0.17 to 1.0.18 in /fuzz
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.17 to 1.0.18.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.17...1.0.18)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 11:50:39 +00:00
dependabot[bot]
507a03e7ee build: Bump cc from 1.0.95 to 1.0.97
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.95 to 1.0.97.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.95...1.0.97)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 11:23:25 +00:00
Purna Pavan Chandra
fe86f90ba6 tests: add back tests_snapshot_restore* but to common_sequential
tests_snapshot_restore* have been earlier removed from common_parallel
due to the falkiness they add testsuite. Running them sequentially would
eliminate the flakiness. Hence, add the tests back to testsuite but into
common_sequential module.

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
3769b18a70 tests: remove test_snapshot_restore* tests from common_parallel
test_snapshot_restore_* tests often have transient failures and add to
overall flakiness of the integration testsuite. Hence, remove them from
common_parallel. However, these tests need to be added back to
common_sequential

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
6d74393833 tests: Add test_snapshot_restore_with_fd to integration tests
VM is created with FDs explicitly passed to CH via --net parameter
and snapshotted. New net FDs are passed in turn during restore.
Boilerplate code from _test_snapshot_restore().

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
26670e4778 docs: Update snapshot/restore documentation
Add a section about restoring VM with new Net FDs explicitly passed to
ch-remote via 'net_fds' parameter

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
555c4c41ab ch-remote: allow fds to be sent along with 'restore'
Enable restore command the ability to send file descriptors along with
HTTP request. This is useful when restoring a VM with explicit FDs
passed to NetConfig(s).

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
b82f25572b vmm: http_endpoint: Change PutHandler for VmRestore
Consume FDs passed via SCM_RIGHTs to VmRestore API and assign them
appropriately to RestoredNetConfig's fds field.

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-05-14 10:52:46 +00:00
Purna Pavan Chandra
584784a0f8 vmm: Support passing Net FDs to Restore
'NetConfig' FDs, when explicitly passed via SCM_RIGHTS during VM
creation, are marked as invalid during snapshot. See: #6332.
So, Restore should support input for the new net FDs. This patch adds
new field 'net_fds' to 'RestoreConfig'. The FDs passed using this new
field are replaced into the 'fds' field of NetConfig appropriately.

The 'validate()' function ensures all net devices from 'VmConfig' backed
by FDs have a corresponding 'RestoreNetConfig' with a matched 'id' and
expected number of FDs.

The unit tests provide different inputs to parse and validate functions
to make sure parsing and error handling is as per expectation.

Fixes #6286

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
Co-authored-by: Bo Chen <chen.bo@intel.com>
2024-05-14 10:52:46 +00:00
Yi Wang
4fd5070f5d ch-remote: fix help of remove-device
remove-device can remove not only VFIO device but also pci device.

No functional change.

Signed-off-by: Yi Wang <foxywang@tencent.com>
2024-05-09 14:34:30 +00:00
Wei Liu
241d1d5cdb hypervisor: kvm: add missing capability requirements
The list is gathered from going through various code paths in the code
base.

No functional change intended.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-09 06:50:57 +00:00
Wei Liu
c07671edb4 hypervisor: kvm: introduce a check_extension macro
That reduces code repetition.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-09 06:50:57 +00:00
Wei Liu
8093820965 hypervisor: kvm: sort the required capabilities
No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-09 06:50:57 +00:00
Wei Liu
86cf50565e hypervisor: kvm: drop the check for Cap::SignalMsi
Per the KVM API document, that capability is only valid with in-kernel
irqchip that handles MSIs.

Through out the code base, there is no call to KVM_IOCTL_SIGNAL_MSI.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-05-09 06:50:57 +00:00
Rob Bradford
95fd684ad7 pci: Remove extra whitespace line from Cargo.toml
This was preventing the Cargo.toml formatter (taplo) from correctly
alphabetically ordering.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 21:46:13 +00:00
Rob Bradford
ce8e76cf94 build: Add GitHub action to run taplo for Cargo.toml formatting
Check that the Cargo.toml files meet the formatting requirements.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 21:46:13 +00:00
Rob Bradford
3f8cd52ffd build: Format Cargo.toml files using taplo
Run the taplo formatter with the newly added configuration file

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 21:46:13 +00:00
Rob Bradford
f9d3c73c15 build: Add taplo configuration file for Cargo.toml files
This configuration enforces the alphebetical ordering of arrays and keys
in the Cargo.toml files.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 21:46:13 +00:00
Rob Bradford
7e25cc2aa0 build: Add "fuzzing" as a valid cfg(..) attribute
The compiler is now able to warn if an invalid attribute (e.g like a
feature) is not available.

See https://blog.rust-lang.org/2024/05/06/check-cfg.html for more
details.

Add build.rs files in the crates that use #cfg(fuzzing) to add fuzzing
to the list of valid cfg attributes.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
Rob Bradford
8b86c7724b build: Bump MSRV to 1.77.0
The ability to control the rustc flags (required for adding new
attributes to the allowed list of #[cfg(..)]) requires bumping the MSRV
to 1.77.0

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
Rob Bradford
ea23c16c5a build: Expose and use "sev_snp" feature on virtio-devices
Code in this crate is conditional on this feature so it necessary to
expose as a new feature and use that feature as a dependency when the
feature is enabled on the vmm crate.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
Rob Bradford
3def18f502 fuzz: Fix use of "guest_debug" conditional code
Enable the use of the vmm crate with the "guest_debug" feature and make
the code that exercises that in the fuzzer unconditional on
"guest_debug" as a feature (as that is not specified as a feature in the
fuzz workspace itself.)

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
Rob Bradford
2bf6f9300a hypervisor: Remove derivations conditional on non-existant feature
The "with-serde" feature does not exist so these [#derive(..)]
statements are never compiled in.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
Rob Bradford
fd43b79f96 build: Correctly enable dhat support in vmm crate
The "dhat-heap" feature needs to be enabled inside the vmm crate as a
depenency from the top-level as there is build time check for that
feature inside the vmm crate.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-08 08:10:28 +00:00
dependabot[bot]
a70808bae9 build: Bump thiserror from 1.0.58 to 1.0.60
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.58 to 1.0.60.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.58...1.0.60)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-08 00:08:24 +00:00
dependabot[bot]
97d617f071 build: Bump windows-targets from 0.52.4 to 0.52.5 in /fuzz
Bumps [windows-targets](https://github.com/microsoft/windows-rs) from 0.52.4 to 0.52.5.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 23:43:32 +00:00
dependabot[bot]
0194a635f7 build: Bump libc from 0.2.153 to 0.2.154 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.153 to 0.2.154.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.153...0.2.154)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 00:15:23 +00:00
dependabot[bot]
e5d0acf0a9 build: Bump concurrent-queue from 2.4.0 to 2.5.0
Bumps [concurrent-queue](https://github.com/smol-rs/concurrent-queue) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/smol-rs/concurrent-queue/releases)
- [Changelog](https://github.com/smol-rs/concurrent-queue/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/concurrent-queue/compare/v2.4.0...v2.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 23:52:00 +00:00
Rob Bradford
622a1a3735 tests: Serialise the live migration/upgrade NUMA/balloon tests
These tests use relatively large memory allocations and if they are
allowed to run in parallel can result in the container encountering an
OOM situation.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-04 10:06:04 +00:00
Rob Bradford
f5abb168e3 tests: Re-enable live upgrade tests
And bump release verion used to v39.0

Fixes: #6134

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-04 10:06:04 +00:00
dependabot[bot]
1e3ef1a548 build: Bump async-recursion from 1.1.0 to 1.1.1
Bumps [async-recursion](https://github.com/dcchut/async-recursion) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/dcchut/async-recursion/releases)
- [Commits](https://github.com/dcchut/async-recursion/compare/v1.1.0...v1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 00:05:22 +00:00
dependabot[bot]
275a63655b build: Bump autocfg from 1.2.0 to 1.3.0 in /fuzz
Bumps [autocfg](https://github.com/cuviper/autocfg) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/cuviper/autocfg/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-03 23:48:51 +00:00
dependabot[bot]
16651db712 build: Bump anstyle-wincon from 3.0.2 to 3.0.3 in /fuzz
Bumps [anstyle-wincon](https://github.com/rust-cli/anstyle) from 3.0.2 to 3.0.3.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.2...anstyle-wincon-v3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-03 08:21:38 +00:00
dependabot[bot]
d03e43facc build: Bump async-task from 4.7.0 to 4.7.1
Bumps [async-task](https://github.com/smol-rs/async-task) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/smol-rs/async-task/releases)
- [Changelog](https://github.com/smol-rs/async-task/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-task/compare/v4.7.0...v4.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 23:42:46 +00:00
dependabot[bot]
c2ed82f3af build: Bump vfio-ioctls from da8c5b6 to df7de6b
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio) from `da8c5b6` to `df7de6b`.
- [Release notes](https://github.com/rust-vmm/vfio/releases)
- [Commits](da8c5b6709...df7de6b256)

---
updated-dependencies:
- dependency-name: vfio-ioctls
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 00:31:05 +00:00
dependabot[bot]
5fc71dec34 build: Bump syn from 2.0.58 to 2.0.60 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.58 to 2.0.60.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.58...2.0.60)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 00:14:18 +00:00
Rob Bradford
d10f20eb71 build: Bump vhost-user-backend, vhost, and virtio-queue
Update the vhost-user-backend crate version used along with related
crates (vhost and virtio-queue.) This requires minor changes to the
types used for the memory in the backends with the use of the
BitmapMmapRegion type for the Bitmap implementation.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-01 18:29:36 +00:00
Rob Bradford
6c0dedd560 block: Replace specific bitmap implementation with trait
Replace the specific Bitmap implementation from the type signature used
for functions that take memory. This allows more flexibility when using
these functions in particular when these functions are used by the
vhost-user-block backend. An updated vhost-user-backend crate requires
extra constraints on the Bitmap implementation used (it must support
BitmapReplace which AtomicBitmap does not.)

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-01 18:29:36 +00:00
Rob Bradford
b29edfbee8 net_util: Replace specific bitmap implementation with trait
Replace the specific Bitmap implementation from the type signature used
for functions that take memory. This allows more flexibility when using
these functions in particular when these functions are used by the
vhost-user-net backend. An updated vhost-user-backend crate requires
extra constraints on the Bitmap implementation used (it must support
BitmapReplace which AtomicBitmap does not.)

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-05-01 18:29:36 +00:00
Bo Chen
75e1dc2bce vmm: openapi: Do not provide default values for required fields
This is to resolve the inconsistencies from our openapi specification,
as default values do not make sense for required fields.

Reported-by: James O. D. Hunt <james.o.hunt@intel.com>
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-05-01 17:31:36 +00:00
dependabot[bot]
6ba4f6de95 build: Bump serde_with from 3.8.0 to 3.8.1 in /fuzz
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.8.0...v3.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 07:35:24 +00:00
Purna Pavan Chandra
de1f055481 tests: Reduce Guest memory in _test_snapshot_restore
Change from default 4G to 2G to reduce the memory usage. This will help
avoid "No disk space left" errors when all snapshot tests run at once.

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-04-30 07:36:59 +00:00
Purna Pavan Chandra
1a94c6c932 tests: clean up snapshot dir after restore
The snapshot_dir is not needed anymore fter the guest is restored.
Hence, remove it. This will potentially avoid transient failures caused
due to insufficient disk space.

Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
2024-04-30 07:36:59 +00:00
Wei Liu
1aeaee221d devices: rtc_pl031: drop TimstampUs
It is not used anywhere in code.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
862a056105 virtio-devices: vsock: fix two clippy warnings
The mem_size field is not needed in TestContext. Drop it.

Make sure guest_evvq is read once. Clippy cannot figured out that it was
used.

While at it, add an extra assert for the spurious rxvq event test, too.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
fe704bd44a arch: simplify MP table signature generation code
Clippy complained one use of the char_array macro.

Instead of fixing that use case, the observation is that the macro was
needed only because MP table types mixed c_char and c_uchar for no
particular reason.

Only use c_uchar in those types, and drop char_array.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
f6cd3bd86d block, pci, rate_limiter, vm-allocator: drop legacy numeric constants
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
0816c8292f pci: drop a useless check
The end_addr is a 64-bit value which cannot possibly be larger than
u64::max_value().

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
319538fbed block: annotate two transmute calls
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
Wei Liu
4f1e74b553 net_util: annotate a transmute call
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-30 07:32:08 +00:00
dependabot[bot]
24f8d15b14 build: Bump jobserver from 0.1.30 to 0.1.31 in /fuzz
Bumps [jobserver](https://github.com/rust-lang/jobserver-rs) from 0.1.30 to 0.1.31.
- [Commits](https://github.com/rust-lang/jobserver-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 00:10:11 +00:00
Rob Bradford
f4b0443489 build: Mark release as draft when creating GitHub releases
The maintainer can then replace the plaintext body (derived from the
tag) with a markdown version and then publish.

As part of 6c4144e943 creating a draft
release was accidentally dropped.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-29 16:47:46 +00:00
Muminul Islam
030d84eb08 vmm: make clock data independent of hypervisor
As MSHV also implements set/get_clock data, this patch
removes the KVM feature guard and make it x86_64 only and
both for KVM and MSHV.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-04-29 16:46:26 +00:00
Muminul Islam
4847f5c4f6 hypervisor: implement clock data for MSHV
This PR implement time reference for Microsoft
Hypervisor based partition/VM.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-04-29 16:46:26 +00:00
Muminul Islam
bf6c9e6447 build: Update mshv crate commit in Cargo.lock
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-04-29 16:46:26 +00:00
Wei Liu
f6d99d9a9b build: use released version of the IGVM crates
No functional change.

While at it, consolidate some of the IGVM related import directives.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2024-04-29 11:13:59 +00:00
Songqian Li
e38a69f0d2 net_util: import derive feature for serde
Import derive feature since `net_util` uses macro
`Serialize` and `Deserialize`.

Fixes: #6421

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-04-29 11:13:05 +00:00
152 changed files with 7193 additions and 2866 deletions

View File

@@ -15,7 +15,7 @@ jobs:
- stable
- beta
- nightly
- "1.74.1"
- "1.77.0"
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
@@ -49,6 +49,9 @@ jobs:
- name: Build (default features + guest_debug)
run: cargo rustc --locked --bin cloud-hypervisor --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (default features + pvmemcontrol)
run: cargo rustc --locked --bin cloud-hypervisor --features "pvmemcontrol" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (mshv)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks

View File

@@ -41,7 +41,7 @@ jobs:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=20240407-0
type=raw,value=20240507-0
type=sha
- name: Build and push

View File

@@ -80,6 +80,13 @@ jobs:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (default features + pvmemcontrol)
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples --features "pvmemcontrol" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (default features + tracing)
uses: actions-rs/cargo@v1
with:

View File

@@ -45,7 +45,7 @@ jobs:
target: ${{ matrix.platform.target }}
args: ${{ matrix.platform.args }}
strip: true
toolchain: 1.74.1
toolchain: "1.77.0"
- name: Copy Release Binaries
if: github.event_name == 'create' && github.event.ref_type == 'tag'
shell: bash
@@ -88,6 +88,7 @@ jobs:
if: github.event_name == 'create' && github.event.ref_type == 'tag'
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
./${{ matrix.platform.name_ch }}
./${{ matrix.platform.name_ch_remote }}

21
.github/workflows/taplo.yaml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Cargo.toml Formatting (taplo)
on:
pull_request:
paths:
- '**/Cargo.toml'
jobs:
cargo_toml_format:
name: Cargo.toml Formatting
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install build dependencies
run: sudo apt-get update && sudo apt-get -yqq install build-essential libssl-dev
- name: Install taplo
run: cargo install taplo-cli --locked
- name: Check formatting
run: taplo fmt --check

5
.taplo.toml Normal file
View File

@@ -0,0 +1,5 @@
include = ["**/Cargo.toml"]
[formatting]
reorder_arrays = true
reorder_keys = true

View File

@@ -112,5 +112,5 @@ Fixes #88
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
```
Then, after the corresponding PR is merged, Github will automatically close that issue when parsing the
Then, after the corresponding PR is merged, GitHub will automatically close that issue when parsing the
[commit message](https://help.github.com/articles/closing-issues-via-commit-messages/).

715
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
[package]
name = "cloud-hypervisor"
version = "39.0.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
default-run = "cloud-hypervisor"
build = "build.rs"
license = "LICENSE-APACHE & LICENSE-BSD-3-Clause"
description = "Open source Virtual Machine Monitor (VMM) that runs on top of KVM"
default-run = "cloud-hypervisor"
description = "Open source Virtual Machine Monitor (VMM) that runs on top of KVM & MSHV"
edition = "2021"
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
license = "Apache-2.0 AND BSD-3-Clause"
name = "cloud-hypervisor"
version = "41.0.0"
# Minimum buildable version:
# Keep in sync with version in .github/workflows/build.yaml
# Policy on MSRV (see #4318):
@@ -15,87 +15,88 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
# 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.74.1"
rust-version = "1.77.0"
[profile.release]
lto = true
codegen-units = 1
lto = true
opt-level = "s"
strip = true
[profile.profiling]
debug = true
inherits = "release"
strip = false
debug = true
[dependencies]
anyhow = "1.0.81"
anyhow = "1.0.86"
api_client = { path = "api_client" }
clap = { version = "4.5.4", features = ["string"] }
dhat = { version = "0.3.3", optional = true }
epoll = "4.3.3"
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
libc = "0.2.153"
log = { version = "0.4.21", features = ["std"] }
libc = "0.2.155"
log = { version = "0.4.22", features = ["std"] }
option_parser = { path = "option_parser" }
seccompiler = "0.4.0"
serde_json = "1.0.115"
serde_json = "1.0.120"
signal-hook = "0.3.17"
thiserror = "1.0.58"
tpm = { path = "tpm"}
thiserror = "1.0.62"
tpm = { path = "tpm" }
tracer = { path = "tracer" }
vm-memory = "0.14.1"
vmm = { path = "vmm" }
vmm-sys-util = "0.12.1"
vm-memory = "0.14.1"
zbus = { version = "3.15.2", optional = true }
zbus = { version = "4.1.2", optional = true }
[dev-dependencies]
dirs = "5.0.1"
net_util = { path = "net_util" }
once_cell = "1.19.0"
serde_json = "1.0.115"
serde_json = "1.0.120"
test_infra = { path = "test_infra" }
wait-timeout = "0.2.0"
# Please adjust `vmm::feature_list()` accordingly when changing the
# feature list below
[features]
default = ["kvm", "io_uring"]
dbus_api = ["zbus", "vmm/dbus_api"]
dhat-heap = ["dhat"] # For heap profiling
dbus_api = ["vmm/dbus_api", "zbus"]
default = ["io_uring", "kvm"]
dhat-heap = ["dhat", "vmm/dhat-heap"] # For heap profiling
guest_debug = ["vmm/guest_debug"]
igvm = ["vmm/igvm", "mshv"]
igvm = ["mshv", "vmm/igvm"]
io_uring = ["vmm/io_uring"]
kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"]
sev_snp = ["igvm", "vmm/sev_snp", "mshv"]
pvmemcontrol = ["vmm/pvmemcontrol"]
sev_snp = ["igvm", "mshv", "vmm/sev_snp"]
tdx = ["vmm/tdx"]
tracing = ["vmm/tracing", "tracer/tracing"]
tracing = ["tracer/tracing", "vmm/tracing"]
[workspace]
members = [
"api_client",
"arch",
"block",
"devices",
"event_monitor",
"hypervisor",
"net_gen",
"net_util",
"option_parser",
"pci",
"performance-metrics",
"rate_limiter",
"serial_buffer",
"test_infra",
"tracer",
"vhost_user_block",
"vhost_user_net",
"virtio-devices",
"vmm",
"vm-allocator",
"vm-device",
"vm-migration",
"vm-virtio"
"api_client",
"arch",
"block",
"devices",
"event_monitor",
"hypervisor",
"net_gen",
"net_util",
"option_parser",
"pci",
"performance-metrics",
"rate_limiter",
"serial_buffer",
"test_infra",
"tracer",
"vhost_user_block",
"vhost_user_net",
"virtio-devices",
"vm-allocator",
"vm-device",
"vm-migration",
"vm-virtio",
"vmm",
]

View File

@@ -1,8 +1,9 @@
[package]
name = "api_client"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
name = "api_client"
version = "0.1.0"
[dependencies]
thiserror = "1.0.62"
vmm-sys-util = "0.12.1"

View File

@@ -3,41 +3,27 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::fmt;
use std::io::{Read, Write};
use std::os::unix::io::RawFd;
use thiserror::Error;
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
#[error("Error writing to or reading from HTTP socket: {0}")]
Socket(std::io::Error),
#[error("Error sending file descriptors: {0}")]
SocketSendFds(vmm_sys_util::errno::Error),
#[error("Error parsing HTTP status code: {0}")]
StatusCodeParsing(std::num::ParseIntError),
#[error("HTTP output is missing protocol statement")]
MissingProtocol,
#[error("Error parsing HTTP Content-Length field: {0}")]
ContentLengthParsing(std::num::ParseIntError),
#[error("Server responded with an error: {0:?}")]
ServerResponse(StatusCode, Option<String>),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Socket(e) => write!(f, "Error writing to or reading from HTTP socket: {e}"),
SocketSendFds(e) => write!(f, "Error writing to or reading from HTTP socket: {e}"),
StatusCodeParsing(e) => write!(f, "Error parsing HTTP status code: {e}"),
MissingProtocol => write!(f, "HTTP output is missing protocol statement"),
ContentLengthParsing(e) => write!(f, "Error parsing HTTP Content-Length field: {e}"),
ServerResponse(s, o) => {
if let Some(o) = o {
write!(f, "Server responded with an error: {s:?}: {o}")
} else {
write!(f, "Server responded with an error: {s:?}")
}
}
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum StatusCode {
Continue,

View File

@@ -1,25 +1,29 @@
[package]
name = "arch"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2021"
name = "arch"
version = "0.1.0"
[features]
default = []
kvm = []
sev_snp = []
tdx = []
[dependencies]
anyhow = "1.0.81"
anyhow = "1.0.86"
byteorder = "1.5.0"
hypervisor = { path = "../hypervisor" }
libc = "0.2.153"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.21"
serde = { version = "1.0.197", features = ["rc", "derive"] }
thiserror = "1.0.58"
libc = "0.2.155"
linux-loader = { version = "0.11.0", features = ["bzimage", "elf", "pe"] }
log = "0.4.22"
serde = { version = "1.0.197", features = ["derive", "rc"] }
thiserror = "1.0.62"
uuid = "1.8.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-bitmap"] }
vm-memory = { version = "0.14.1", features = [
"backend-bitmap",
"backend-mmap",
] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }

View File

@@ -26,6 +26,7 @@ use super::layout::{
};
use std::fs;
use std::path::Path;
use thiserror::Error;
use vm_fdt::{FdtWriter, FdtWriterResult};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryRegion};
@@ -80,9 +81,10 @@ pub trait DeviceInfoForFdt {
}
/// Errors thrown while configuring the Flattened Device Tree for aarch64.
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Failure in writing FDT in memory.
#[error("Failure in writing FDT in memory: {0}")]
WriteFdtToMemory(GuestMemoryError),
}
type Result<T> = result::Result<T, Error>;
@@ -523,7 +525,7 @@ fn create_memory_node(
let memory_region_size: u64 = memory_region.size() as u64;
mem_reg_prop.push(memory_region_start_addr);
mem_reg_prop.push(memory_region_size);
// Set the node address the first non-zero regison address
// Set the node address the first non-zero region address
if node_memory_addr == 0 {
node_memory_addr = memory_region_start_addr;
}
@@ -569,7 +571,7 @@ fn create_memory_node(
if ram_regions.len() > 2 {
panic!(
"There should be up to two non-continuous regions, devidided by the
"There should be up to two non-continuous regions, divided by the
gap at the end of 32bit address space."
);
}
@@ -894,7 +896,7 @@ fn create_pci_nodes(
for pci_device_info_elem in pci_device_info.iter() {
// EDK2 requires the PCIe high space above 4G address.
// The actual space in CLH follows the RAM. If the RAM space is small, the PCIe high space
// could fall bellow 4G.
// could fall below 4G.
// Here we cut off PCI device space below 8G in FDT to workaround the EDK2 check.
// But the address written in ACPI is not impacted.
let (pci_device_base_64bit, pci_device_size_64bit) =

View File

@@ -18,32 +18,40 @@ use log::{log_enabled, Level};
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use thiserror::Error;
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
pub const _NSIG: i32 = 65;
/// Errors thrown while configuring aarch64 system.
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Failed to create a FDT.
#[error("Failed to create a FDT")]
SetupFdt,
/// Failed to write FDT to memory.
#[error("Failed to write FDT to memory: {0}")]
WriteFdtToMemory(fdt::Error),
/// Failed to create a GIC.
#[error("Failed to create a GIC")]
SetupGic,
/// Failed to compute the initramfs address.
#[error("Failed to compute the initramfs address")]
InitramfsAddress,
/// Error configuring the general purpose registers
#[error("Error configuring the general purpose registers: {0}")]
RegsConfiguration(hypervisor::HypervisorCpuError),
/// Error configuring the MPIDR register
#[error("Error configuring the MPIDR register: {0}")]
VcpuRegMpidr(hypervisor::HypervisorCpuError),
/// Error initializing PMU for vcpu
#[error("Error initializing PMU for vcpu")]
VcpuInitPmu,
}

View File

@@ -5,18 +5,23 @@
use std::io::{Read, Seek, SeekFrom};
use std::os::fd::AsFd;
use std::result;
use thiserror::Error;
use vm_memory::{GuestAddress, GuestMemory};
/// Errors thrown while loading UEFI binary
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Unable to seek to UEFI image start.
#[error("Unable to seek to UEFI image start")]
SeekUefiStart,
/// Unable to seek to UEFI image end.
#[error("Unable to seek to UEFI image end")]
SeekUefiEnd,
/// UEFI image too big.
#[error("UEFI image too big")]
UefiTooBig,
/// Unable to read UEFI image
#[error("Unable to read UEFI image")]
ReadUefiImage,
}
type Result<T> = result::Result<T, Error>;

View File

@@ -23,6 +23,7 @@ use linux_loader::loader::elf::start_info::{
};
use std::collections::BTreeMap;
use std::mem;
use thiserror::Error;
use vm_memory::{
Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryRegion, GuestUsize,
@@ -33,6 +34,7 @@ use std::arch::x86_64;
pub mod tdx;
// CPUID feature bits
#[cfg(feature = "kvm")]
const TSC_DEADLINE_TIMER_ECX_BIT: u8 = 24; // tsc deadline timer ecx bit.
const HYPERVISOR_ECX_BIT: u8 = 31; // Hypervisor ecx bit.
const MTRR_EDX_BIT: u8 = 12; // Hypervisor ecx bit.
@@ -127,64 +129,83 @@ pub struct CpuidConfig {
pub amx: bool,
}
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Error writing MP table to memory.
#[error("Error writing MP table to memory: {0}")]
MpTableSetup(mptable::Error),
/// Error configuring the general purpose registers
#[error("Error configuring the general purpose registers: {0}")]
RegsConfiguration(regs::Error),
/// Error configuring the special registers
#[error("Error configuring the special registers: {0}")]
SregsConfiguration(regs::Error),
/// Error configuring the floating point related registers
#[error("Error configuring the floating point related registers: {0}")]
FpuConfiguration(regs::Error),
/// Error configuring the MSR registers
#[error("Error configuring the MSR registers: {0}")]
MsrsConfiguration(regs::Error),
/// Failed to set supported CPUs.
#[error("Failed to set supported CPUs: {0}")]
SetSupportedCpusFailed(anyhow::Error),
/// Cannot set the local interruption due to bad configuration.
#[error("Cannot set the local interruption due to bad configuration: {0}")]
LocalIntConfiguration(anyhow::Error),
/// Error setting up SMBIOS table
#[error("Error setting up SMBIOS table: {0}")]
SmbiosSetup(smbios::Error),
/// Could not find any SGX EPC section
#[error("Could not find any SGX EPC section")]
NoSgxEpcSection,
/// Missing SGX CPU feature
#[error("Missing SGX CPU feature")]
MissingSgxFeature,
/// Missing SGX_LC CPU feature
#[error("Missing SGX_LC CPU feature")]
MissingSgxLaunchControlFeature,
/// Error getting supported CPUID through the hypervisor (kvm/mshv) API
#[error("Error getting supported CPUID through the hypervisor API: {0}")]
CpuidGetSupported(HypervisorError),
/// Error populating CPUID with KVM HyperV emulation details
#[error("Error populating CPUID with KVM HyperV emulation details: {0}")]
CpuidKvmHyperV(vmm_sys_util::fam::Error),
/// Error populating CPUID with CPU identification
#[error("Error populating CPUID with CPU identification: {0}")]
CpuidIdentification(vmm_sys_util::fam::Error),
/// Error checking CPUID compatibility
#[error("Error checking CPUID compatibility")]
CpuidCheckCompatibility,
// Error writing EBDA address
#[error("Error writing EBDA address: {0}")]
EbdaSetup(vm_memory::GuestMemoryError),
// Error getting CPU TSC frequency
#[error("Error getting CPU TSC frequency: {0}")]
GetTscFrequency(HypervisorCpuError),
/// Error retrieving TDX capabilities through the hypervisor (kvm/mshv) API
#[cfg(feature = "tdx")]
#[error("Error retrieving TDX capabilities through the hypervisor API: {0}")]
TdxCapabilities(HypervisorError),
/// Failed to configure E820 map for bzImage
#[error("Failed to configure E820 map for bzImage")]
E820Configuration,
}
@@ -557,7 +578,7 @@ impl CpuidFeatureEntry {
if !entry_compatible {
error!(
"Detected incompatible CPUID entry: leaf={:#02x} (subleaf={:#02x}), register='{:?}', \
compatilbe_check='{:?}', source VM feature='{:#04x}', destination VM feature'{:#04x}'.",
compatible_check='{:?}', source VM feature='{:#04x}', destination VM feature'{:#04x}'.",
entry.function, entry.index, entry.feature_reg,
entry.compatible_check, src_vm_feature, dest_vm_feature
);
@@ -599,17 +620,8 @@ pub fn generate_common_cpuid(
"Generating guest CPUID for with physical address size: {}",
config.phys_bits
);
let cpuid_patches = vec![
// Patch tsc deadline timer bit
CpuidPatch {
function: 1,
index: 0,
flags_bit: None,
eax_bit: None,
ebx_bit: None,
ecx_bit: Some(TSC_DEADLINE_TIMER_ECX_BIT),
edx_bit: None,
},
#[allow(unused_mut)]
let mut cpuid_patches = vec![
// Patch hypervisor bit
CpuidPatch {
function: 1,
@@ -632,6 +644,23 @@ pub fn generate_common_cpuid(
},
];
#[cfg(feature = "kvm")]
if matches!(
hypervisor.hypervisor_type(),
hypervisor::HypervisorType::Kvm
) {
// Patch tsc deadline timer bit
cpuid_patches.push(CpuidPatch {
function: 1,
index: 0,
flags_bit: None,
eax_bit: None,
ebx_bit: None,
ecx_bit: Some(TSC_DEADLINE_TIMER_ECX_BIT),
edx_bit: None,
});
}
// Supported CPUID
let mut cpuid = hypervisor
.get_supported_cpuid()
@@ -682,6 +711,20 @@ pub fn generate_common_cpuid(
}
}
}
// Copy host L1 cache details if not populated by KVM
0x8000_0005 => {
if entry.eax == 0 && entry.ebx == 0 && entry.ecx == 0 && entry.edx == 0 {
// SAFETY: cpuid called with valid leaves
if unsafe { std::arch::x86_64::__cpuid(0x8000_0000).eax } >= 0x8000_0005 {
// SAFETY: cpuid called with valid leaves
let leaf = unsafe { std::arch::x86_64::__cpuid(0x8000_0005) };
entry.eax = leaf.eax;
entry.ebx = leaf.ebx;
entry.ecx = leaf.ecx;
entry.edx = leaf.edx;
}
}
}
// Copy host L2 cache details if not populated by KVM
0x8000_0006 => {
if entry.eax == 0 && entry.ebx == 0 && entry.ecx == 0 && entry.edx == 0 {
@@ -800,12 +843,17 @@ pub fn configure_vcpu(
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x8000_001e, Some(0), CpuidReg::EAX, x2apic_id);
}
// Set ApicId in cpuid for each vcpu
// SAFETY: get host cpuid when eax=1
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx;
cpu_ebx &= 0xffffff;
cpu_ebx |= x2apic_id << 24;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
// Set ApicId in cpuid for each vcpu - found in cpuid ebx when eax = 1
let mut apic_id_patched = false;
for entry in &mut cpuid {
if entry.function == 1 {
entry.ebx &= 0xffffff;
entry.ebx |= x2apic_id << 24;
apic_id_patched = true;
break;
}
}
assert!(apic_id_patched);
if let Some(t) = topology {
update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id);

View File

@@ -17,7 +17,7 @@ pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpf_intel {
pub signature: [::std::os::raw::c_char; 4usize],
pub signature: [::std::os::raw::c_uchar; 4usize],
pub physptr: ::std::os::raw::c_uint,
pub length: ::std::os::raw::c_uchar,
pub specification: ::std::os::raw::c_uchar,
@@ -32,12 +32,12 @@ pub struct mpf_intel {
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_table {
pub signature: [::std::os::raw::c_char; 4usize],
pub signature: [::std::os::raw::c_uchar; 4usize],
pub length: ::std::os::raw::c_ushort,
pub spec: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub oem: [::std::os::raw::c_char; 8usize],
pub productid: [::std::os::raw::c_char; 12usize],
pub spec: ::std::os::raw::c_uchar,
pub checksum: ::std::os::raw::c_uchar,
pub oem: [::std::os::raw::c_uchar; 8usize],
pub productid: [::std::os::raw::c_uchar; 12usize],
pub oemptr: ::std::os::raw::c_uint,
pub oemsize: ::std::os::raw::c_ushort,
pub oemcount: ::std::os::raw::c_ushort,
@@ -106,9 +106,9 @@ pub struct mpc_lintsrc {
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_oemtable {
pub signature: [::std::os::raw::c_char; 4usize],
pub signature: [::std::os::raw::c_uchar; 4usize],
pub length: ::std::os::raw::c_ushort,
pub rev: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub mpc: [::std::os::raw::c_char; 8usize],
pub rev: ::std::os::raw::c_uchar,
pub checksum: ::std::os::raw::c_uchar,
pub mpc: [::std::os::raw::c_uchar; 8usize],
}

View File

@@ -8,10 +8,11 @@
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::{get_x2apic_id, mpspec};
use crate::GuestMemoryMmap;
use libc::c_char;
use libc::c_uchar;
use std::mem;
use std::result;
use std::slice;
use thiserror::Error;
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
@@ -49,29 +50,40 @@ unsafe impl ByteValued for MpcLintsrcWrapper {}
// SAFETY: see above
unsafe impl ByteValued for MpfIntelWrapper {}
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// There was too little guest memory to store the entire MP table.
#[error("There was too little guest memory to store the entire MP table")]
NotEnoughMemory,
/// The MP table has too little address space to be stored.
#[error("The MP table has too little address space to be stored")]
AddressOverflow,
/// Failure while zeroing out the memory for the MP table.
#[error("Failure while zeroing out the memory for the MP table: {0}")]
Clear(GuestMemoryError),
/// Number of CPUs exceeds the maximum supported CPUs
#[error("Number of CPUs exceeds the maximum supported CPUs")]
TooManyCpus,
/// Failure to write the MP floating pointer.
#[error("Failure to write the MP floating pointer: {0}")]
WriteMpfIntel(GuestMemoryError),
/// Failure to write MP CPU entry.
#[error("Failure to write MP CPU entry: {0}")]
WriteMpcCpu(GuestMemoryError),
/// Failure to write MP ioapic entry.
#[error("Failure to write MP ioapic entry: {0}")]
WriteMpcIoapic(GuestMemoryError),
/// Failure to write MP bus entry.
#[error("Failure to write MP bus entry: {0}")]
WriteMpcBus(GuestMemoryError),
/// Failure to write MP interrupt source entry.
#[error("Failure to write MP interrupt source entry: {0}")]
WriteMpcIntsrc(GuestMemoryError),
/// Failure to write MP local interrupt source entry.
#[error("Failure to write MP local interrupt source entry: {0}")]
WriteMpcLintsrc(GuestMemoryError),
/// Failure to write MP table header.
#[error("Failure to write MP table header: {0}")]
WriteMpcTable(GuestMemoryError),
}
@@ -82,18 +94,13 @@ pub type Result<T> = result::Result<T, Error>;
// a large number for FC usecases.
pub const MAX_SUPPORTED_CPUS: u32 = 254;
// Convenience macro for making arrays of diverse character types.
macro_rules! char_array {
($t:ty; $( $c:expr ),*) => ( [ $( $c as $t ),* ] )
}
// Most of these variables are sourced from the Intel MP Spec 1.4.
const SMP_MAGIC_IDENT: [c_char; 4] = char_array!(c_char; '_', 'M', 'P', '_');
const MPC_SIGNATURE: [c_char; 4] = char_array!(c_char; 'P', 'C', 'M', 'P');
const MPC_SPEC: i8 = 4;
const MPC_OEM: [c_char; 8] = char_array!(c_char; 'F', 'C', ' ', ' ', ' ', ' ', ' ', ' ');
const MPC_PRODUCT_ID: [c_char; 12] = ['0' as c_char; 12];
const BUS_TYPE_ISA: [u8; 6] = char_array!(u8; 'I', 'S', 'A', ' ', ' ', ' ');
const SMP_MAGIC_IDENT: &[c_uchar; 4] = b"_MP_";
const MPC_SIGNATURE: &[c_uchar; 4] = b"PCMP";
const MPC_SPEC: u8 = 4;
const MPC_OEM: &[c_uchar; 8] = b"FC ";
const MPC_PRODUCT_ID: &[c_uchar; 12] = &[b'0'; 12];
const BUS_TYPE_ISA: &[c_uchar; 6] = b"ISA ";
const APIC_VERSION: u8 = 0x14;
const CPU_STEPPING: u32 = 0x600;
const CPU_FEATURE_APIC: u32 = 0x200;
@@ -168,7 +175,7 @@ pub fn setup_mptable(
{
let mut mpf_intel = MpfIntelWrapper(mpspec::mpf_intel::default());
let size = mem::size_of::<MpfIntelWrapper>() as u64;
mpf_intel.0.signature = SMP_MAGIC_IDENT;
mpf_intel.0.signature = *SMP_MAGIC_IDENT;
mpf_intel.0.length = 1;
mpf_intel.0.specification = 4;
mpf_intel.0.physptr = (base_mp.raw_value() + size) as u32;
@@ -209,7 +216,7 @@ pub fn setup_mptable(
let mut mpc_bus = MpcBusWrapper(mpspec::mpc_bus::default());
mpc_bus.0.type_ = mpspec::MP_BUS as u8;
mpc_bus.0.busid = 0;
mpc_bus.0.bustype = BUS_TYPE_ISA;
mpc_bus.0.bustype = *BUS_TYPE_ISA;
mem.write_obj(mpc_bus, base_mp)
.map_err(Error::WriteMpcBus)?;
base_mp = base_mp.unchecked_add(size as u64);
@@ -280,14 +287,14 @@ pub fn setup_mptable(
{
let mut mpc_table = MpcTableWrapper(mpspec::mpc_table::default());
mpc_table.0.signature = MPC_SIGNATURE;
mpc_table.0.signature = *MPC_SIGNATURE;
mpc_table.0.length = table_end.unchecked_offset_from(table_base) as u16;
mpc_table.0.spec = MPC_SPEC;
mpc_table.0.oem = MPC_OEM;
mpc_table.0.productid = MPC_PRODUCT_ID;
mpc_table.0.oem = *MPC_OEM;
mpc_table.0.productid = *MPC_PRODUCT_ID;
mpc_table.0.lapic = APIC_START.0 as u32;
checksum = checksum.wrapping_add(compute_checksum(&mpc_table.0));
mpc_table.0.checksum = (!checksum).wrapping_add(1) as i8;
mpc_table.0.checksum = (!checksum).wrapping_add(1);
mem.write_obj(mpc_table, table_base)
.map_err(Error::WriteMpcTable)?;
}

View File

@@ -15,33 +15,46 @@ use hypervisor::arch::x86::regs::CR0_PE;
use hypervisor::arch::x86::{FpuState, SpecialRegisters, StandardRegisters};
use std::sync::Arc;
use std::{mem, result};
use thiserror::Error;
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError};
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Failed to get SREGs for this CPU.
#[error("Failed to get SREGs for this CPU: {0}")]
GetStatusRegisters(hypervisor::HypervisorCpuError),
/// Failed to set base registers for this CPU.
#[error("Failed to set base registers for this CPU: {0}")]
SetBaseRegisters(hypervisor::HypervisorCpuError),
/// Failed to configure the FPU.
#[error("Failed to configure the FPU: {0}")]
SetFpuRegisters(hypervisor::HypervisorCpuError),
/// Setting up MSRs failed.
#[error("Setting up MSRs failed: {0}")]
SetModelSpecificRegisters(hypervisor::HypervisorCpuError),
/// Failed to set SREGs for this CPU.
#[error("Failed to set SREGs for this CPU: {0}")]
SetStatusRegisters(hypervisor::HypervisorCpuError),
/// Checking the GDT address failed.
#[error("Checking the GDT address failed")]
CheckGdtAddr,
/// Writing the GDT to RAM failed.
#[error("Writing the GDT to RAM failed: {0}")]
WriteGdt(GuestMemoryError),
/// Writing the IDT to RAM failed.
#[error("Writing the IDT to RAM failed: {0}")]
WriteIdt(GuestMemoryError),
/// Writing PDPTE to RAM failed.
#[error("Writing PDPTE to RAM failed: {0}")]
WritePdpteAddress(GuestMemoryError),
/// Writing PDE to RAM failed.
#[error("Writing PDE to RAM failed: {0}")]
WritePdeAddress(GuestMemoryError),
/// Writing PML4 to RAM failed.
#[error("Writing PML4 to RAM failed: {0}")]
WritePml4Address(GuestMemoryError),
/// Writing PML5 to RAM failed.
#[error("Writing PML5 to RAM failed: {0}")]
WritePml5Address(GuestMemoryError),
}

View File

@@ -8,53 +8,36 @@
use crate::layout::SMBIOS_START;
use crate::GuestMemoryMmap;
use std::fmt::{self, Display};
use std::mem;
use std::result;
use std::slice;
use thiserror::Error;
use uuid::Uuid;
use vm_memory::ByteValued;
use vm_memory::{Address, Bytes, GuestAddress};
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// There was too little guest memory to store the entire SMBIOS table.
#[error("There was too little guest memory to store the SMBIOS table")]
NotEnoughMemory,
/// The SMBIOS table has too little address space to be stored.
#[error("The SMBIOS table has too little address space to be stored")]
AddressOverflow,
/// Failure while zeroing out the memory for the SMBIOS table.
#[error("Failure while zeroing out the memory for the SMBIOS table")]
Clear,
/// Failure to write SMBIOS entrypoint structure
#[error("Failure to write SMBIOS entrypoint structure")]
WriteSmbiosEp,
/// Failure to write additional data to memory
#[error("Failure to write additional data to memory")]
WriteData,
/// Failure to parse uuid, uuid format may be error
#[error("Failure to parse uuid: {0}")]
ParseUuid(uuid::Error),
}
impl std::error::Error for Error {}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
let description = match self {
NotEnoughMemory => {
"There was too little guest memory to store the SMBIOS table".to_string()
}
AddressOverflow => {
"The SMBIOS table has too little address space to be stored".to_string()
}
Clear => "Failure while zeroing out the memory for the SMBIOS table".to_string(),
WriteSmbiosEp => "Failure to write SMBIOS entrypoint structure".to_string(),
WriteData => "Failure to write additional data to memory".to_string(),
ParseUuid(e) => format!("Failure to parse uuid: {e}"),
};
write!(f, "SMBIOS error: {description}")
}
}
pub type Result<T> = result::Result<T, Error>;
// Constants sourced from SMBIOS Spec 3.2.0.

View File

@@ -1,8 +1,8 @@
[package]
authors = ["The Chromium OS Authors", "The Cloud Hypervisor Authors"]
edition = "2021"
name = "block"
version = "0.1.0"
edition = "2021"
authors = ["The Cloud Hypervisor Authors", "The Chromium OS Authors"]
[features]
default = []
@@ -12,15 +12,19 @@ io_uring = ["dep:io-uring"]
byteorder = "1.5.0"
crc-any = "2.4.4"
io-uring = { version = "0.6.3", optional = true }
libc = "0.2.153"
log = "0.4.21"
remain = "0.2.13"
libc = "0.2.155"
log = "0.4.22"
remain = "0.2.14"
serde = { version = "1.0.197", features = ["derive"] }
smallvec = "1.13.2"
thiserror = "1.0.58"
thiserror = "1.0.62"
uuid = { version = "1.8.0", features = ["v4"] }
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
virtio-queue = "0.11.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
virtio-queue = "0.12.0"
vm-memory = { version = "0.14.1", features = [
"backend-atomic",
"backend-bitmap",
"backend-mmap",
] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1"

View File

@@ -56,16 +56,14 @@ use thiserror::Error;
use virtio_bindings::virtio_blk::*;
use virtio_queue::DescriptorChain;
use vm_memory::{
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
GuestMemoryError, GuestMemoryLoadGuard,
bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError,
GuestMemoryLoadGuard,
};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
const SECTOR_SHIFT: u8 = 9;
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
@@ -166,8 +164,8 @@ pub enum ExecuteError {
}
impl ExecuteError {
pub fn status(&self) -> u32 {
match *self {
pub fn status(&self) -> u8 {
let status = match *self {
ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
@@ -182,7 +180,8 @@ impl ExecuteError {
ExecuteError::AsyncWrite(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::AsyncFlush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::TemporaryBufferAllocation(_) => VIRTIO_BLK_S_IOERR,
}
};
status as u8
}
}
@@ -195,8 +194,8 @@ pub enum RequestType {
Unsupported(u32),
}
pub fn request_type(
mem: &GuestMemoryMmap,
pub fn request_type<B: Bitmap + 'static>(
mem: &vm_memory::GuestMemoryMmap<B>,
desc_addr: GuestAddress,
) -> result::Result<RequestType, Error> {
let type_ = mem.read_obj(desc_addr).map_err(Error::GuestMemory)?;
@@ -209,7 +208,10 @@ pub fn request_type(
}
}
fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64, Error> {
fn sector<B: Bitmap + 'static>(
mem: &vm_memory::GuestMemoryMmap<B>,
desc_addr: GuestAddress,
) -> result::Result<u64, Error> {
const SECTOR_OFFSET: usize = 8;
let addr = match mem.checked_offset(desc_addr, SECTOR_OFFSET) {
Some(v) => v,
@@ -239,16 +241,15 @@ pub struct Request {
}
impl Request {
pub fn parse(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap>>,
pub fn parse<B: Bitmap + 'static>(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
access_platform: Option<&Arc<dyn AccessPlatform>>,
) -> result::Result<Request, Error> {
let hdr_desc = desc_chain
.next()
.ok_or(Error::DescriptorChainTooShort)
.map_err(|e| {
.inspect_err(|_| {
error!("Missing head descriptor");
e
})?;
// The head contains the request type which MUST be readable.
@@ -274,9 +275,8 @@ impl Request {
let mut desc = desc_chain
.next()
.ok_or(Error::DescriptorChainTooShort)
.map_err(|e| {
.inspect_err(|_| {
error!("Only head descriptor present: request = {:?}", req);
e
})?;
if !desc.has_next() {
@@ -307,9 +307,8 @@ impl Request {
desc = desc_chain
.next()
.ok_or(Error::DescriptorChainTooShort)
.map_err(|e| {
.inspect_err(|_| {
error!("DescriptorChain corrupted: request = {:?}", req);
e
})?;
}
status_desc = desc;
@@ -331,11 +330,11 @@ impl Request {
Ok(req)
}
pub fn execute<T: Seek + Read + Write>(
pub fn execute<T: Seek + Read + Write, B: Bitmap + 'static>(
&self,
disk: &mut T,
disk_nsectors: u64,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
serial: &[u8],
) -> result::Result<u32, ExecuteError> {
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
@@ -388,9 +387,9 @@ impl Request {
Ok(len)
}
pub fn execute_async(
pub fn execute_async<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
disk_nsectors: u64,
disk_image: &mut dyn AsyncIo,
serial: &[u8],
@@ -658,7 +657,9 @@ where
let mut slices: SmallVec<[IoSliceMut; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSliceMut wraps around libc::iovec
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
slices.push(IoSliceMut::new(unsafe {
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
}));
}
let result = {
@@ -691,7 +692,9 @@ where
let mut slices: SmallVec<[IoSlice; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSlice wraps around libc::iovec
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
slices.push(IoSlice::new(unsafe {
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
}));
}
let result = {

View File

@@ -19,11 +19,11 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use libc::{EINVAL, ENOSPC, ENOTSUP};
use remain::sorted;
use std::cmp::{max, min};
use std::fmt::{self, Display};
use std::fs::OpenOptions;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::mem::size_of;
use std::str;
use thiserror::Error;
use vmm_sys_util::{
file_traits::FileSetLen, file_traits::FileSync, seek_hole::SeekHole, write_zeroes::PunchHole,
write_zeroes::WriteZeroesAt,
@@ -31,106 +31,98 @@ use vmm_sys_util::{
pub use crate::qcow::raw_file::RawFile;
/// Nesting depth limit for disk formats that can open other disk files.
const MAX_NESTING_DEPTH: u32 = 10;
#[sorted]
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
#[error("Backing file io error: {0}")]
BackingFileIo(io::Error),
BackingFileOpen(Box<crate::Error>),
#[error("Backing file open error: {0}")]
BackingFileOpen(Box<Error>),
#[error("Backing file name is too long: {0} bytes over")]
BackingFileTooLong(usize),
#[error("Compressed blocks not supported")]
CompressedBlocksNotSupported,
#[error("Failed to evict cache: {0}")]
EvictingCache(io::Error),
#[error("File larger than max of {}: {0}", MAX_QCOW_FILE_SIZE)]
FileTooBig(u64),
#[error("Failed to get file size: {0}")]
GettingFileSize(io::Error),
#[error("Failed to get refcount: {0}")]
GettingRefcount(refcount::Error),
#[error("Failed to parse filename: {0}")]
InvalidBackingFileName(str::Utf8Error),
#[error("Invalid cluster index")]
InvalidClusterIndex,
#[error("Invalid cluster size")]
InvalidClusterSize,
#[error("Invalid index")]
InvalidIndex,
#[error("Invalid L1 table offset")]
InvalidL1TableOffset,
#[error("Invalid L1 table size: {0}")]
InvalidL1TableSize(u32),
#[error("Invalid magic")]
InvalidMagic,
#[error("Invalid offset: {0}")]
InvalidOffset(u64),
#[error("Invalid refcount table offset")]
InvalidRefcountTableOffset,
#[error("Invalid refcount table size: {0}")]
InvalidRefcountTableSize(u64),
#[error("Maximum disk nesting depth exceeded")]
MaxNestingDepthExceeded,
#[error("No free clusters")]
NoFreeClusters,
#[error("No refcount clusters")]
NoRefcountClusters,
#[error("Not enough space for refcounts")]
NotEnoughSpaceForRefcounts,
#[error("Failed to open file {0}")]
OpeningFile(io::Error),
#[error("Failed to read data: {0}")]
ReadingData(io::Error),
#[error("Failed to read header: {0}")]
ReadingHeader(io::Error),
#[error("Failed to read pointers: {0}")]
ReadingPointers(io::Error),
#[error("Failed to read ref count block: {0}")]
ReadingRefCountBlock(refcount::Error),
#[error("Failed to read ref counts: {0}")]
ReadingRefCounts(io::Error),
#[error("Failed to rebuild ref counts: {0}")]
RebuildingRefCounts(io::Error),
#[error("Refcount table offset past file end")]
RefcountTableOffEnd,
#[error("Too many clusters specified for refcount")]
RefcountTableTooLarge,
#[error("Failed to seek file: {0}")]
SeekingFile(io::Error),
#[error("Failed to set file size: {0}")]
SettingFileSize(io::Error),
#[error("Failed to set refcount refcount: {0}")]
SettingRefcountRefcount(io::Error),
#[error("Size too small for number of clusters")]
SizeTooSmallForNumberOfClusters,
#[error("L1 entry table too large: {0}")]
TooManyL1Entries(u64),
#[error("Ref count table too large: {0}")]
TooManyRefcounts(u64),
#[error("Unsupported refcount order")]
UnsupportedRefcountOrder,
#[error("Unsupported version: {0}")]
UnsupportedVersion(u32),
#[error("Failed to write data: {0}")]
WritingData(io::Error),
#[error("Failed to write header: {0}")]
WritingHeader(io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
#[remain::check]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
#[sorted]
match self {
BackingFileIo(e) => write!(f, "backing file io error: {}", e),
BackingFileOpen(e) => write!(f, "backing file open error: {}", *e),
BackingFileTooLong(len) => {
write!(f, "backing file name is too long: {} bytes over", len)
}
CompressedBlocksNotSupported => write!(f, "compressed blocks not supported"),
EvictingCache(e) => write!(f, "failed to evict cache: {e}"),
FileTooBig(size) => write!(f, "file larger than max of {MAX_QCOW_FILE_SIZE}: {size}"),
GettingFileSize(e) => write!(f, "failed to get file size: {e}"),
GettingRefcount(e) => write!(f, "failed to get refcount: {e}"),
InvalidBackingFileName(e) => write!(f, "failed to parse filename: {}", e),
InvalidClusterIndex => write!(f, "invalid cluster index"),
InvalidClusterSize => write!(f, "invalid cluster size"),
InvalidIndex => write!(f, "invalid index"),
InvalidL1TableOffset => write!(f, "invalid L1 table offset"),
InvalidL1TableSize(size) => write!(f, "invalid L1 table size {size}"),
InvalidMagic => write!(f, "invalid magic"),
InvalidOffset(_) => write!(f, "invalid offset"),
InvalidRefcountTableOffset => write!(f, "invalid refcount table offset"),
InvalidRefcountTableSize(size) => write!(f, "invalid refcount table size: {size}"),
NoFreeClusters => write!(f, "no free clusters"),
NoRefcountClusters => write!(f, "no refcount clusters"),
NotEnoughSpaceForRefcounts => write!(f, "not enough space for refcounts"),
OpeningFile(e) => write!(f, "failed to open file: {e}"),
ReadingData(e) => write!(f, "failed to read data: {e}"),
ReadingHeader(e) => write!(f, "failed to read header: {e}"),
ReadingPointers(e) => write!(f, "failed to read pointers: {e}"),
ReadingRefCountBlock(e) => write!(f, "failed to read ref count block: {e}"),
ReadingRefCounts(e) => write!(f, "failed to read ref counts: {e}"),
RebuildingRefCounts(e) => write!(f, "failed to rebuild ref counts: {e}"),
RefcountTableOffEnd => write!(f, "refcount table offset past file end"),
RefcountTableTooLarge => write!(f, "too many clusters specified for refcount table"),
SeekingFile(e) => write!(f, "failed to seek file: {e}"),
SettingFileSize(e) => write!(f, "failed to set file size: {e}"),
SettingRefcountRefcount(e) => write!(f, "failed to set refcount refcount: {e}"),
SizeTooSmallForNumberOfClusters => write!(f, "size too small for number of clusters"),
TooManyL1Entries(count) => write!(f, "l1 entry table too large: {count}"),
TooManyRefcounts(count) => write!(f, "ref count table too large: {count}"),
UnsupportedRefcountOrder => write!(f, "unsupported refcount order"),
UnsupportedVersion(v) => write!(f, "unsupported version: {v}"),
WritingData(e) => write!(f, "failed to write data: {e}"),
WritingHeader(e) => write!(f, "failed to write header: {e}"),
}
}
}
pub enum ImageType {
Raw,
Qcow2,
@@ -447,12 +439,20 @@ pub struct QcowFile {
// List of unreferenced clusters available to be used. unref clusters become available once the
// removal of references to them have been synced to disk.
avail_clusters: Vec<u64>,
backing_file: Option<Box<dyn BlockBackend>>,
backing_file: Option<Box<Self>>,
}
impl QcowFile {
/// Creates a QcowFile from `file`. File must be a valid qcow2 image.
pub fn from(mut file: RawFile) -> Result<QcowFile> {
///
/// Additionally, max nesting depth of this qcow2 image will be set to default value 10.
pub fn from(file: RawFile) -> Result<QcowFile> {
Self::from_with_nesting_depth(file, MAX_NESTING_DEPTH)
}
/// Creates a QcowFile from `file` and with a max nesting depth. File must be a valid qcow2
/// image.
pub fn from_with_nesting_depth(mut file: RawFile, max_nesting_depth: u32) -> Result<QcowFile> {
let header = QcowHeader::new(&mut file)?;
// Only v2 and v3 files are supported.
@@ -479,14 +479,20 @@ impl QcowFile {
let direct_io = file.is_direct();
let backing_file = if let Some(backing_file_path) = header.backing_file_path.as_ref() {
if max_nesting_depth == 0 {
return Err(Error::MaxNestingDepthExceeded);
}
let path = backing_file_path.clone();
let backing_raw_file = OpenOptions::new()
.read(true)
.open(path)
.map_err(Error::BackingFileIo)?;
let backing_file = crate::create_disk_file(backing_raw_file, direct_io)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
Some(backing_file)
let backing_file = Self::from_with_nesting_depth(
RawFile::new(backing_raw_file, direct_io),
max_nesting_depth - 1,
)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
Some(Box::new(backing_file))
} else {
None
};
@@ -634,20 +640,22 @@ impl QcowFile {
file: RawFile,
version: u32,
backing_file_name: &str,
backing_file_max_nesting_depth: u32,
) -> Result<QcowFile> {
let direct_io = file.is_direct();
let backing_raw_file = OpenOptions::new()
.read(true)
.open(backing_file_name)
.map_err(Error::BackingFileIo)?;
let backing_file = crate::create_disk_file(backing_raw_file, direct_io)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let size = backing_file
.size()
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let backing_file = Self::from_with_nesting_depth(
RawFile::new(backing_raw_file, direct_io),
backing_file_max_nesting_depth,
)
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
let size = backing_file.virtual_size();
let header = QcowHeader::create_for_size_and_path(version, size, Some(backing_file_name))?;
let mut result = QcowFile::new_from_header(file, header)?;
result.backing_file = Some(backing_file);
result.backing_file = Some(Box::new(backing_file));
Ok(result)
}
@@ -675,7 +683,7 @@ impl QcowFile {
Ok(qcow)
}
pub fn set_backing_file(&mut self, backing: Option<Box<dyn BlockBackend>>) {
pub fn set_backing_file(&mut self, backing: Option<Box<Self>>) {
self.backing_file = backing;
}
@@ -1213,7 +1221,7 @@ impl QcowFile {
}
// Allocate and initialize a new data cluster. Returns the offset of the
// cluster in to the file on success.
// cluster into the file on success.
fn append_data_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64> {
let new_addr: u64 = self.get_new_cluster(initial_data)?;
// The cluster refcount starts at one indicating it is used but doesn't need COW.
@@ -1631,7 +1639,7 @@ impl PunchHole for QcowFile {
let mut remaining = length;
let mut offset = offset;
while remaining > 0 {
let chunk_length = min(remaining, std::usize::MAX as u64) as usize;
let chunk_length = min(remaining, usize::MAX as u64) as usize;
self.deallocate_bytes(offset, chunk_length)?;
remaining -= chunk_length as u64;
offset += chunk_length as u64;
@@ -1791,11 +1799,17 @@ where
/// Copy the contents of a disk image in `src_file` into `dst_file`.
/// The type of `src_file` is automatically detected, and the output file type is
/// determined by `dst_type`.
pub fn convert(mut src_file: RawFile, dst_file: RawFile, dst_type: ImageType) -> Result<()> {
pub fn convert(
mut src_file: RawFile,
dst_file: RawFile,
dst_type: ImageType,
src_max_nesting_depth: u32,
) -> Result<()> {
let src_type = detect_image_type(&mut src_file)?;
match src_type {
ImageType::Qcow2 => {
let mut src_reader = QcowFile::from(src_file)?;
let mut src_reader =
QcowFile::from_with_nesting_depth(src_file, src_max_nesting_depth)?;
convert_reader(&mut src_reader, dst_file, dst_type)
}
ImageType::Raw => {
@@ -1824,6 +1838,9 @@ pub fn detect_image_type(file: &mut RawFile) -> Result<ImageType> {
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
use std::path::Path;
use vmm_sys_util::tempdir::TempDir;
use vmm_sys_util::tempfile::TempFile;
use vmm_sys_util::write_zeroes::WriteZeroes;
@@ -2023,6 +2040,82 @@ mod tests {
assert_eq!(read_header.backing_file_path, header.backing_file_path);
}
#[test]
fn no_backing_file() {
// `backing_file` is `None`
let header = QcowHeader::create_for_size_and_path(3, 0x10_0000, None)
.expect("Failed to create header.");
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
header
.write_to(&mut disk_file)
.expect("Failed to write header to shm.");
disk_file.rewind().unwrap();
// The maximum nesting depth is 0, which means backing file is not allowed.
let res = QcowFile::from_with_nesting_depth(disk_file, 0);
assert!(res.is_ok());
}
#[test]
fn disable_backing_file() {
// `backing_file` is `Some`
let header =
QcowHeader::create_for_size_and_path(3, 0x10_0000, Some("/path/to/backing/file"))
.expect("Failed to create header.");
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
header
.write_to(&mut disk_file)
.expect("Failed to write header to shm.");
disk_file.rewind().unwrap();
// The maximum nesting depth is 0, which means backing file is not allowed.
let res = QcowFile::from_with_nesting_depth(disk_file, 0);
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), Error::MaxNestingDepthExceeded));
}
/// Create a qcow2 file with itself as its backing file.
///
/// Without configuration `max_nesting_depth`, this will cause infinite recursion when loading
/// the file until stack overflow.
fn new_self_referential_qcow(path: &Path) -> Result<()> {
let header = QcowHeader::create_for_size_and_path(3, 0x10_0000, path.to_str())?;
let mut disk_file = RawFile::new(
File::create(path).expect("Failed to create image file."),
false,
);
header.write_to(&mut disk_file)?;
Ok(())
}
#[test]
fn max_nesting_backing() {
let test_dir = TempDir::new_with_prefix("/tmp/ch").unwrap();
let img_path = test_dir.as_path().join("test.img");
new_self_referential_qcow(img_path.as_path()).unwrap();
let err = QcowFile::from_with_nesting_depth(
RawFile::new(
File::open(img_path.as_path()).expect("Failed to open qcow image file"),
false,
),
MAX_NESTING_DEPTH,
)
.expect_err("Opening qcow file with itself as backing file should fail.");
// This type of error is complex. For comparing easily, we can check if it contains the
// type name after formatting.
assert!(format!("{err:?}").contains(&format!("{:?}", Error::MaxNestingDepthExceeded)));
// This should recursively call the function ten times before throwing an error, and the
// error `BackingFileOpen` should also be repeated ten times.
assert_eq!(
format!("{err:?}")
.matches("BackingFileOpen")
.collect::<Vec<_>>()
.len() as u32,
MAX_NESTING_DEPTH,
);
}
#[test]
fn invalid_magic() {
let invalid_header = vec![0x51u8, 0x46, 0x4a, 0xfb];

View File

@@ -4,50 +4,37 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::fmt::{self, Display};
use std::io;
use libc::EINVAL;
use thiserror::Error;
use crate::qcow::{
qcow_raw_file::QcowRawFile,
vec_cache::{CacheMap, Cacheable, VecCache},
};
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// `EvictingCache` - Error writing a refblock from the cache to disk.
#[error("Failed to write a refblock from the cache to disk: {0}")]
EvictingRefCounts(io::Error),
/// `InvalidIndex` - Address requested isn't within the range of the disk.
#[error("Address requested is not within the range of the disk")]
InvalidIndex,
/// `NeedCluster` - Handle this error by reading the cluster and calling the function again.
#[error("Cluster with addr={0} needs to be read")]
NeedCluster(u64),
/// `NeedNewCluster` - Handle this error by allocating a cluster and calling the function again.
#[error("New cluster needs to be allocated for refcounts")]
NeedNewCluster,
/// `ReadingRefCounts` - Error reading the file in to the refcount cache.
/// `ReadingRefCounts` - Error reading the file into the refcount cache.
#[error("Failed to read the file into the refcount cache: {0}")]
ReadingRefCounts(io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match self {
EvictingRefCounts(e) => {
write!(f, "failed to write a refblock from the cache to disk: {e}")
}
InvalidIndex => write!(f, "address requested is not within the range of the disk"),
NeedCluster(addr) => write!(f, "cluster with addr={addr} needs to be read"),
NeedNewCluster => write!(f, "new cluster needs to be allocated for refcounts"),
ReadingRefCounts(e) => {
write!(f, "failed to read the file into the refcount cache: {e}")
}
}
}
}
/// Represents the refcount entries for an open qcow file.
#[derive(Clone, Debug)]
pub struct RefCount {

View File

@@ -127,7 +127,7 @@ pub struct Header {
impl Header {
/// Reads the Header structure from a reference VHDx file
pub fn new(f: &mut File, start: u64) -> Result<Header> {
// Read the whole header in to a buffer. We will need it for
// Read the whole header into a buffer. We will need it for
// calculating checksum.
let mut buffer = [0; HEADER_SIZE as usize];
f.seek(SeekFrom::Start(start))
@@ -470,7 +470,7 @@ impl VhdxHeader {
pub fn calculate_checksum(buffer: &mut [u8], csum_offset: usize) -> Result<u32> {
// Read the checksum into a mutable slice
let csum_buf = &mut buffer[csum_offset..csum_offset + 4];
// Convert the checksum chunk in to a u32 integer
// Convert the checksum chunk into a u32 integer
let orig_csum = LittleEndian::read_u32(csum_buf);
// Zero the checksum in the buffer
LittleEndian::write_u32(csum_buf, 0);

View File

@@ -1,26 +1,31 @@
[package]
name = "devices"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2021"
name = "devices"
version = "0.1.0"
[dependencies]
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
anyhow = "1.0.81"
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
anyhow = "1.0.86"
arch = { path = "../arch" }
bitflags = "2.5.0"
bitflags = "2.6.0"
byteorder = "1.5.0"
event_monitor = { path = "../event_monitor" }
hypervisor = { path = "../hypervisor" }
libc = "0.2.153"
log = "0.4.21"
libc = "0.2.155"
log = "0.4.22"
num_enum = "0.7.2"
pci = { path = "../pci" }
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.58"
thiserror = "1.0.62"
tpm = { path = "../tpm" }
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = "0.14.1"
vm-memory = { version = "0.14.1", features = [
"backend-atomic",
"backend-bitmap",
"backend-mmap",
] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = "0.12.1"
@@ -29,3 +34,4 @@ arch = { path = "../arch" }
[features]
default = []
pvmemcontrol = []

View File

@@ -4,31 +4,42 @@
use std::io;
use std::result;
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd;
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Invalid trigger mode.
#[error("Invalid trigger mode")]
InvalidTriggerMode,
/// Invalid delivery mode.
#[error("Invalid delivery mode")]
InvalidDeliveryMode,
/// Failed creating the interrupt source group.
#[error("Failed creating the interrupt source group: {0}")]
CreateInterruptSourceGroup(io::Error),
/// Failed triggering the interrupt.
#[error("Failed triggering the interrupt: {0}")]
TriggerInterrupt(io::Error),
/// Failed masking the interrupt.
#[error("Failed masking the interrupt: {0}")]
MaskInterrupt(io::Error),
/// Failed unmasking the interrupt.
#[error("Failed unmasking the interrupt: {0}")]
UnmaskInterrupt(io::Error),
/// Failed updating the interrupt.
#[error("Failed updating the interrupt: {0}")]
UpdateInterrupt(io::Error),
/// Failed enabling the interrupt.
#[error("Failed enabling the interrupt: {0}")]
EnableInterrupt(io::Error),
#[cfg(target_arch = "aarch64")]
/// Failed creating GIC device.
#[error("Failed creating GIC device: {0}")]
CreateGic(hypervisor::HypervisorVmError),
#[cfg(target_arch = "aarch64")]
/// Failed restoring GIC device.
#[error("Failed restoring GIC device: {0}")]
RestoreGic(hypervisor::arch::aarch64::gic::Error),
}

View File

@@ -416,7 +416,7 @@ impl InterruptController for Ioapic {
self.interrupt_source_group
.trigger(irq as InterruptIndex)
.map_err(Error::TriggerInterrupt)?;
debug!("Interrupt successfully delivered");
debug!("Interrupt {irq} successfully delivered");
// If trigger mode is level sensitive, set the Remote IRR bit.
// It will be cleared when the EOI is received.

View File

@@ -9,9 +9,10 @@
use crate::{read_le_u32, write_le_u32};
use serde::{Deserialize, Serialize};
use std::io;
use std::result;
use std::sync::{Arc, Barrier};
use std::{fmt, io};
use thiserror::Error;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
@@ -37,29 +38,18 @@ const GPIO_ID_HIGH: u64 = 0x1000;
const N_GPIOS: u32 = 8;
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
#[error("Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("GPIO interrupt disabled by guest driver.")]
GpioInterruptDisabled,
#[error("Could not trigger GPIO interrupt: {0}.")]
GpioInterruptFailure(io::Error),
#[error("Invalid GPIO Input key triggered: {0}.")]
GpioTriggerKeyFailure(u32),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {offset}"),
Error::GpioInterruptDisabled => write!(f, "GPIO interrupt disabled by guest driver.",),
Error::GpioInterruptFailure(ref e) => {
write!(f, "Could not trigger GPIO interrupt: {e}.")
}
Error::GpioTriggerKeyFailure(key) => {
write!(f, "Invalid GPIO Input key triggered: {key}.")
}
}
}
}
type Result<T> = result::Result<T, Error>;
/// A GPIO device following the PL061 specification.

View File

@@ -9,10 +9,10 @@
//! a real-time clock input.
//!
use crate::{read_le_u32, write_le_u32};
use std::fmt;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use std::{io, result};
use thiserror::Error;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
@@ -39,21 +39,14 @@ const AMBA_ID_HIGH: u64 = 0x1000;
/// Constant to convert seconds to nanoseconds.
pub const NANOS_PER_SECOND: u64 = 1_000_000_000;
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
#[error("Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("Failed to trigger interrupt: {0}")]
InterruptFailure(io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {offset}"),
Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {e}"),
}
}
}
type Result<T> = result::Result<T, Error>;
/// Wrapper over `libc::clockid_t` to specify Linux Kernel clock source.
@@ -79,98 +72,6 @@ impl From<ClockType> for libc::clockid_t {
}
}
/// Structure representing the date in local time with nanosecond precision.
pub struct LocalTime {
/// Seconds in current minute.
sec: i32,
/// Minutes in current hour.
min: i32,
/// Hours in current day, 24H format.
hour: i32,
/// Days in current month.
mday: i32,
/// Months in current year.
mon: i32,
/// Years passed since 1900 BC.
year: i32,
/// Nanoseconds in current second.
nsec: i64,
}
impl LocalTime {
/// Returns the [LocalTime](struct.LocalTime.html) structure for the calling moment.
#[cfg(test)]
pub fn now() -> LocalTime {
let mut timespec = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
let mut tm: libc::tm = libc::tm {
tm_sec: 0,
tm_min: 0,
tm_hour: 0,
tm_mday: 0,
tm_mon: 0,
tm_year: 0,
tm_wday: 0,
tm_yday: 0,
tm_isdst: 0,
tm_gmtoff: 0,
tm_zone: std::ptr::null(),
};
// SAFETY: the parameters are valid.
unsafe {
libc::clock_gettime(libc::CLOCK_REALTIME, &mut timespec);
libc::localtime_r(&timespec.tv_sec, &mut tm);
}
LocalTime {
sec: tm.tm_sec,
min: tm.tm_min,
hour: tm.tm_hour,
mday: tm.tm_mday,
mon: tm.tm_mon,
year: tm.tm_year,
nsec: timespec.tv_nsec,
}
}
}
impl fmt::Display for LocalTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}-{:02}-{:02}T{:02}:{:02}:{:02}.{:09}",
self.year + 1900,
self.mon + 1,
self.mday,
self.hour,
self.min,
self.sec,
self.nsec
)
}
}
/// Holds a micro-second resolution timestamp with both the real time and cpu time.
#[derive(Clone)]
pub struct TimestampUs {
/// Real time in microseconds.
pub time_us: u64,
/// Cpu time in microseconds.
pub cputime_us: u64,
}
impl Default for TimestampUs {
fn default() -> TimestampUs {
TimestampUs {
time_us: get_time(ClockType::Monotonic) / 1000,
cputime_us: get_time(ClockType::ProcessCpu) / 1000,
}
}
}
/// Returns a timestamp in nanoseconds based on the provided clock type.
///
/// # Arguments
@@ -337,6 +238,70 @@ mod tests {
const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
struct LocalTime {
sec: i32,
min: i32,
hour: i32,
mday: i32,
mon: i32,
year: i32,
nsec: i64,
}
impl LocalTime {
fn now() -> LocalTime {
let mut timespec = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
let mut tm: libc::tm = libc::tm {
tm_sec: 0,
tm_min: 0,
tm_hour: 0,
tm_mday: 0,
tm_mon: 0,
tm_year: 0,
tm_wday: 0,
tm_yday: 0,
tm_isdst: 0,
tm_gmtoff: 0,
tm_zone: std::ptr::null(),
};
// SAFETY: the parameters are valid.
unsafe {
libc::clock_gettime(libc::CLOCK_REALTIME, &mut timespec);
libc::localtime_r(&timespec.tv_sec, &mut tm);
}
LocalTime {
sec: tm.tm_sec,
min: tm.tm_min,
hour: tm.tm_hour,
mday: tm.tm_mday,
mon: tm.tm_mon,
year: tm.tm_year,
nsec: timespec.tv_nsec,
}
}
}
impl std::fmt::Display for LocalTime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}-{:02}-{:02}T{:02}:{:02}:{:02}.{:09}",
self.year + 1900,
self.mon + 1,
self.mday,
self.hour,
self.min,
self.sec,
self.nsec
)
}
}
#[test]
fn test_get_time() {
for _ in 0..1000 {

View File

@@ -411,14 +411,11 @@ mod tests {
None,
);
serial.write(0, DATA as u64, &[b'x', b'y']);
serial.write(0, DATA as u64, &[b'a']);
serial.write(0, DATA as u64, &[b'b']);
serial.write(0, DATA as u64, &[b'c']);
assert_eq!(
serial_out.buf.lock().unwrap().as_slice(),
&[b'a', b'b', b'c']
);
serial.write(0, DATA as u64, b"xy");
serial.write(0, DATA as u64, b"a");
serial.write(0, DATA as u64, b"b");
serial.write(0, DATA as u64, b"c");
assert_eq!(serial_out.buf.lock().unwrap().as_slice(), b"abc");
}
#[test]
@@ -436,7 +433,7 @@ mod tests {
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
serial.write(0, IER as u64, &[IER_RECV_BIT]);
serial.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
serial.queue_input_bytes(b"abc").unwrap();
assert_eq!(intr_evt.read().unwrap(), 2);
@@ -473,7 +470,7 @@ mod tests {
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
serial.write(0, IER as u64, &[IER_THR_BIT]);
serial.write(0, DATA as u64, &[b'a']);
serial.write(0, DATA as u64, b"a");
assert_eq!(intr_evt.read().unwrap(), 2);
let mut data = [0u8];
@@ -515,9 +512,9 @@ mod tests {
);
serial.write(0, MCR as u64, &[MCR_LOOP_BIT]);
serial.write(0, DATA as u64, &[b'a']);
serial.write(0, DATA as u64, &[b'b']);
serial.write(0, DATA as u64, &[b'c']);
serial.write(0, DATA as u64, b"a");
serial.write(0, DATA as u64, b"b");
serial.write(0, DATA as u64, b"c");
let mut data = [0u8];
serial.read(0, MSR as u64, &mut data[..]);

View File

@@ -9,10 +9,10 @@
use crate::{read_le_u32, write_le_u32};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use std::{io, result};
use thiserror::Error;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
@@ -45,27 +45,20 @@ const PL011_ID: [u8; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
const AMBA_ID_LOW: u64 = 0x3f8;
const AMBA_ID_HIGH: u64 = 0x401;
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
#[error("pl011_write: Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("pl011: DMA not implemented.")]
DmaNotImplemented,
#[error("Failed to trigger interrupt: {0}")]
InterruptFailure(io::Error),
#[error("Failed to write: {0}")]
WriteAllFailure(io::Error),
#[error("Failed to flush: {0}")]
FlushFailure(io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::BadWriteOffset(offset) => write!(f, "pl011_write: Bad Write Offset: {offset}"),
Error::DmaNotImplemented => write!(f, "pl011: DMA not implemented."),
Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {e}"),
Error::WriteAllFailure(e) => write!(f, "Failed to write: {e}"),
Error::FlushFailure(e) => write!(f, "Failed to flush: {e}"),
}
}
}
type Result<T> = result::Result<T, Error>;
/// A PL011 device following the PL011 specification.
@@ -531,14 +524,11 @@ mod tests {
None,
);
pl011.write(0, UARTDR, &[b'x', b'y']);
pl011.write(0, UARTDR, &[b'a']);
pl011.write(0, UARTDR, &[b'b']);
pl011.write(0, UARTDR, &[b'c']);
assert_eq!(
pl011_out.buf.lock().unwrap().as_slice(),
&[b'x', b'a', b'b', b'c']
);
pl011.write(0, UARTDR, b"xy");
pl011.write(0, UARTDR, b"a");
pl011.write(0, UARTDR, b"b");
pl011.write(0, UARTDR, b"c");
assert_eq!(pl011_out.buf.lock().unwrap().as_slice(), b"xabc");
}
#[test]
@@ -556,7 +546,7 @@ mod tests {
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
// counter doesn't change (for 0 it blocks)
assert!(intr_evt.write(1).is_ok());
pl011.queue_input_bytes(&[b'a', b'b', b'c']).unwrap();
pl011.queue_input_bytes(b"abc").unwrap();
assert_eq!(intr_evt.read().unwrap(), 2);

View File

@@ -23,6 +23,8 @@ pub mod interrupt_controller;
#[cfg(target_arch = "x86_64")]
pub mod ioapic;
pub mod legacy;
#[cfg(feature = "pvmemcontrol")]
pub mod pvmemcontrol;
pub mod pvpanic;
pub mod tpm;

819
devices/src/pvmemcontrol.rs Normal file
View File

@@ -0,0 +1,819 @@
// Copyright © 2024 Google LLC
//
// SPDX-License-Identifier: Apache-2.0
//
use num_enum::TryFromPrimitive;
use pci::{
BarReprogrammingParams, PciBarConfiguration, PciBarPrefetchable, PciBarRegionType,
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
};
use std::{
collections::HashMap,
ffi::CString,
io, result,
sync::{Arc, Barrier, Mutex, RwLock},
};
use thiserror::Error;
use vm_allocator::{page_size::get_page_size, AddressAllocator, SystemAllocator};
use vm_device::{BusDeviceSync, Resource};
use vm_memory::{
bitmap::AtomicBitmap, Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory,
GuestMemoryAtomic, GuestMemoryError, GuestMemoryMmap, Le32, Le64,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
const PVMEMCONTROL_VENDOR_ID: u16 = 0x1ae0;
const PVMEMCONTROL_DEVICE_ID: u16 = 0x0087;
const PVMEMCONTROL_SUBSYSTEM_VENDOR_ID: u16 = 0x1ae0;
const PVMEMCONTROL_SUBSYSTEM_ID: u16 = 0x011F;
const MAJOR_VERSION: u64 = 1;
const MINOR_VERSION: u64 = 0;
#[derive(Error, Debug)]
pub enum Error {
// device errors
#[error("Guest gave us bad memory addresses: {0}")]
GuestMemory(#[source] GuestMemoryError),
#[error("Guest sent us invalid request")]
InvalidRequest,
#[error("Guest sent us invalid command: {0}")]
InvalidCommand(u32),
#[error("Guest sent us invalid connection: {0}")]
InvalidConnection(u32),
// pvmemcontrol errors
#[error("Request contains invalid arguments: {0}")]
InvalidArgument(u64),
#[error("Unknown function code: {0}")]
UnknownFunctionCode(u64),
#[error("Libc call fail: {0}")]
LibcFail(#[source] std::io::Error),
}
#[derive(Copy, Clone)]
enum PvmemcontrolSubclass {
Other = 0x80,
}
impl PciSubclass for PvmemcontrolSubclass {
fn get_register_value(&self) -> u8 {
*self as u8
}
}
/// commands have 0 as the most significant byte
#[repr(u32)]
#[derive(PartialEq, Eq, Copy, Clone, TryFromPrimitive)]
enum PvmemcontrolTransportCommand {
Reset = 0x060f_e6d2,
Register = 0x0e35_9539,
Ready = 0x0ca8_d227,
Disconnect = 0x030f_5da0,
Ack = 0x03cf_5196,
Error = 0x01fb_a249,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct PvmemcontrolTransportRegister {
buf_phys_addr: Le64,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct PvmemcontrolTransportRegisterResponse {
command: Le32,
_padding: u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
union PvmemcontrolTransportUnion {
register: PvmemcontrolTransportRegister,
register_response: PvmemcontrolTransportRegisterResponse,
unit: (),
}
#[repr(C)]
#[derive(Copy, Clone)]
struct PvmemcontrolTransport {
payload: PvmemcontrolTransportUnion,
command: PvmemcontrolTransportCommand,
}
const PVMEMCONTROL_DEVICE_MMIO_SIZE: u64 = std::mem::size_of::<PvmemcontrolTransport>() as u64;
const PVMEMCONTROL_DEVICE_MMIO_ALIGN: u64 = std::mem::align_of::<PvmemcontrolTransport>() as u64;
impl PvmemcontrolTransport {
fn ack() -> Self {
PvmemcontrolTransport {
payload: PvmemcontrolTransportUnion { unit: () },
command: PvmemcontrolTransportCommand::Ack,
}
}
fn error() -> Self {
PvmemcontrolTransport {
payload: PvmemcontrolTransportUnion { unit: () },
command: PvmemcontrolTransportCommand::Error,
}
}
fn register_response(command: u32) -> Self {
PvmemcontrolTransport {
payload: PvmemcontrolTransportUnion {
register_response: PvmemcontrolTransportRegisterResponse {
command: command.into(),
_padding: 0,
},
},
command: PvmemcontrolTransportCommand::Ack,
}
}
unsafe fn as_register(self) -> PvmemcontrolTransportRegister {
self.payload.register
}
}
// SAFETY: Contains no references and does not have compiler-inserted padding
unsafe impl ByteValued for PvmemcontrolTransportUnion {}
// SAFETY: Contains no references and does not have compiler-inserted padding
unsafe impl ByteValued for PvmemcontrolTransport {}
#[repr(u64)]
#[derive(Copy, Clone, TryFromPrimitive, Debug)]
enum FunctionCode {
Info = 0,
Dontneed = 1,
Remove = 2,
Free = 3,
Pageout = 4,
Dontdump = 5,
SetVMAAnonName = 6,
Mlock = 7,
Munlock = 8,
MprotectNone = 9,
MprotectR = 10,
MprotectW = 11,
MprotectRW = 12,
Mergeable = 13,
Unmergeable = 14,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
struct PvmemcontrolReq {
func_code: Le64,
addr: Le64,
length: Le64,
arg: Le64,
}
// SAFETY: it only has data and has no implicit padding.
unsafe impl ByteValued for PvmemcontrolReq {}
#[repr(C)]
#[derive(Copy, Clone, Default)]
struct PvmemcontrolResp {
ret_errno: Le32,
ret_code: Le32,
ret_value: Le64,
arg0: Le64,
arg1: Le64,
}
impl std::fmt::Debug for PvmemcontrolResp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let PvmemcontrolResp {
ret_errno,
ret_code,
..
} = self;
write!(
f,
"PvmemcontrolResp {{ ret_errno: {}, ret_code: {}, .. }}",
ret_errno.to_native(),
ret_code.to_native()
)
}
}
// SAFETY: it only has data and has no implicit padding.
unsafe impl ByteValued for PvmemcontrolResp {}
/// The guest connections start at 0x8000_0000, which has a leading 1 in
/// the most significant byte, this ensures it does not conflict with
/// any of the transport commands
#[derive(Hash, Clone, Copy, PartialEq, Eq, Debug)]
pub struct GuestConnection {
command: u32,
}
impl Default for GuestConnection {
fn default() -> Self {
GuestConnection::new(0x8000_0000)
}
}
impl GuestConnection {
fn new(command: u32) -> Self {
Self { command }
}
fn next(&self) -> Self {
let GuestConnection { command } = *self;
if command == u32::MAX {
GuestConnection::default()
} else {
GuestConnection::new(command + 1)
}
}
}
impl TryFrom<u32> for GuestConnection {
type Error = Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
if (value & 0x8000_0000) != 0 {
Ok(GuestConnection::new(value))
} else {
Err(Error::InvalidConnection(value))
}
}
}
struct PercpuInitState {
port_buf_map: HashMap<GuestConnection, GuestAddress>,
next_conn: GuestConnection,
}
impl PercpuInitState {
fn new() -> Self {
PercpuInitState {
port_buf_map: HashMap::new(),
next_conn: GuestConnection::default(),
}
}
}
enum PvmemcontrolState {
PercpuInit(PercpuInitState),
Ready(HashMap<GuestConnection, GuestAddress>),
Broken,
}
pub struct PvmemcontrolDevice {
transport: PvmemcontrolTransport,
state: PvmemcontrolState,
}
impl PvmemcontrolDevice {
fn new(transport: PvmemcontrolTransport, state: PvmemcontrolState) -> Self {
PvmemcontrolDevice { transport, state }
}
}
impl PvmemcontrolDevice {
fn register_percpu_buf(
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
mut state: PercpuInitState,
PvmemcontrolTransportRegister { buf_phys_addr }: PvmemcontrolTransportRegister,
) -> Self {
// access to this address is checked
let buf_phys_addr = GuestAddress(buf_phys_addr.into());
if !guest_memory.memory().check_range(
buf_phys_addr,
std::mem::size_of::<PvmemcontrolResp>().max(std::mem::size_of::<PvmemcontrolReq>()),
) {
warn!("guest sent invalid phys addr {:#x}", buf_phys_addr.0);
return PvmemcontrolDevice::new(
PvmemcontrolTransport::error(),
PvmemcontrolState::Broken,
);
}
let conn = {
// find an available port+byte combination, and fail if full
let mut next_conn = state.next_conn;
while state.port_buf_map.contains_key(&next_conn) {
next_conn = next_conn.next();
if next_conn == state.next_conn {
warn!("connections exhausted");
return PvmemcontrolDevice::new(
PvmemcontrolTransport::error(),
PvmemcontrolState::Broken,
);
}
}
next_conn
};
state.next_conn = conn.next();
state.port_buf_map.insert(conn, buf_phys_addr);
// inform guest of the connection
let response = PvmemcontrolTransport::register_response(conn.command);
PvmemcontrolDevice::new(response, PvmemcontrolState::PercpuInit(state))
}
fn reset() -> Self {
PvmemcontrolDevice::new(
PvmemcontrolTransport::ack(),
PvmemcontrolState::PercpuInit(PercpuInitState::new()),
)
}
fn error() -> Self {
PvmemcontrolDevice::new(PvmemcontrolTransport::error(), PvmemcontrolState::Broken)
}
fn ready(PercpuInitState { port_buf_map, .. }: PercpuInitState) -> Self {
PvmemcontrolDevice::new(
PvmemcontrolTransport::ack(),
PvmemcontrolState::Ready(port_buf_map),
)
}
fn run_command(
&mut self,
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
command: PvmemcontrolTransportCommand,
) {
let state = std::mem::replace(&mut self.state, PvmemcontrolState::Broken);
*self = match command {
PvmemcontrolTransportCommand::Reset => Self::reset(),
PvmemcontrolTransportCommand::Register => {
if let PvmemcontrolState::PercpuInit(state) = state {
// SAFETY: By device protocol. If driver is wrong the device
// can enter a Broken state, but the behavior is still sound.
Self::register_percpu_buf(guest_memory, state, unsafe {
self.transport.as_register()
})
} else {
debug!("received register without reset");
Self::error()
}
}
PvmemcontrolTransportCommand::Ready => {
if let PvmemcontrolState::PercpuInit(state) = state {
Self::ready(state)
} else {
debug!("received ready without reset");
Self::error()
}
}
PvmemcontrolTransportCommand::Disconnect => Self::error(),
PvmemcontrolTransportCommand::Ack => {
debug!("received ack as command");
Self::error()
}
PvmemcontrolTransportCommand::Error => {
debug!("received error as command");
Self::error()
}
}
}
/// read from the transport
fn read_transport(&self, offset: u64, data: &mut [u8]) {
self.transport
.as_slice()
.iter()
.skip(offset as usize)
.zip(data.iter_mut())
.for_each(|(src, dest)| *dest = *src)
}
/// can only write to transport payload
/// command is a special register that needs separate dispatching
fn write_transport(&mut self, offset: u64, data: &[u8]) {
self.transport
.payload
.as_mut_slice()
.iter_mut()
.skip(offset as usize)
.zip(data.iter())
.for_each(|(dest, src)| *dest = *src)
}
fn find_connection(&self, conn: GuestConnection) -> Option<GuestAddress> {
match &self.state {
PvmemcontrolState::Ready(map) => map.get(&conn).copied(),
_ => None,
}
}
}
pub struct PvmemcontrolBusDevice {
mem: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
dev: RwLock<PvmemcontrolDevice>,
}
pub struct PvmemcontrolPciDevice {
id: String,
configuration: PciConfiguration,
bar_regions: Vec<PciBarConfiguration>,
}
impl PvmemcontrolBusDevice {
/// f is called with the host address of `range_base` and only when
/// [`range_base`, `range_base` + `range_len`) is present in the guest
fn operate_on_memory_range<F>(&self, addr: u64, length: u64, f: F) -> result::Result<(), Error>
where
F: FnOnce(*mut libc::c_void, libc::size_t) -> libc::c_int,
{
let memory = self.mem.memory();
let range_base = GuestAddress(addr);
let range_len = usize::try_from(length).map_err(|_| Error::InvalidRequest)?;
// assume guest memory is not interleaved with vmm memory on the host.
if !memory.check_range(range_base, range_len) {
return Err(Error::GuestMemory(GuestMemoryError::InvalidGuestAddress(
range_base,
)));
}
let hva = memory
.get_host_address(range_base)
.map_err(Error::GuestMemory)?;
let res = f(hva as *mut libc::c_void, range_len as libc::size_t);
if res != 0 {
return Err(Error::LibcFail(io::Error::last_os_error()));
}
Ok(())
}
fn madvise(&self, addr: u64, length: u64, advice: libc::c_int) -> result::Result<(), Error> {
// SAFETY: [`base`, `base` + `len`) is guest memory
self.operate_on_memory_range(addr, length, |base, len| unsafe {
libc::madvise(base, len, advice)
})
}
fn mlock(&self, addr: u64, length: u64, on_default: bool) -> result::Result<(), Error> {
// SAFETY: [`base`, `base` + `len`) is guest memory
self.operate_on_memory_range(addr, length, |base, len| unsafe {
libc::mlock2(base, len, if on_default { libc::MLOCK_ONFAULT } else { 0 })
})
}
fn munlock(&self, addr: u64, length: u64) -> result::Result<(), Error> {
// SAFETY: [`base`, `base` + `len`) is guest memory
self.operate_on_memory_range(addr, length, |base, len| unsafe {
libc::munlock(base, len)
})
}
fn mprotect(
&self,
addr: u64,
length: u64,
protection: libc::c_int,
) -> result::Result<(), Error> {
// SAFETY: [`base`, `base` + `len`) is guest memory
self.operate_on_memory_range(addr, length, |base, len| unsafe {
libc::mprotect(base, len, protection)
})
}
fn set_vma_anon_name(&self, addr: u64, length: u64, name: u64) -> result::Result<(), Error> {
let name = (name != 0).then(|| CString::new(format!("pvmemcontrol-{}", name)).unwrap());
let name_ptr = if let Some(name) = &name {
name.as_ptr()
} else {
std::ptr::null()
};
debug!("addr {:X} length {} name {:?}", addr, length, name);
// SAFETY: [`base`, `base` + `len`) is guest memory
self.operate_on_memory_range(addr, length, |base, len| unsafe {
libc::prctl(
libc::PR_SET_VMA,
libc::PR_SET_VMA_ANON_NAME,
base,
len,
name_ptr,
)
})
}
fn process_request(
&self,
func_code: FunctionCode,
addr: u64,
length: u64,
arg: u64,
) -> Result<PvmemcontrolResp, Error> {
let result = match func_code {
FunctionCode::Info => {
return Ok(PvmemcontrolResp {
ret_errno: 0.into(),
ret_code: 0.into(),
ret_value: get_page_size().into(),
arg0: MAJOR_VERSION.into(),
arg1: MINOR_VERSION.into(),
})
}
FunctionCode::Dontneed => self.madvise(addr, length, libc::MADV_DONTNEED),
FunctionCode::Remove => self.madvise(addr, length, libc::MADV_REMOVE),
FunctionCode::Free => self.madvise(addr, length, libc::MADV_FREE),
FunctionCode::Pageout => self.madvise(addr, length, libc::MADV_PAGEOUT),
FunctionCode::Dontdump => self.madvise(addr, length, libc::MADV_DONTDUMP),
FunctionCode::SetVMAAnonName => self.set_vma_anon_name(addr, length, arg),
FunctionCode::Mlock => self.mlock(addr, length, false),
FunctionCode::Munlock => self.munlock(addr, length),
FunctionCode::MprotectNone => self.mprotect(addr, length, libc::PROT_NONE),
FunctionCode::MprotectR => self.mprotect(addr, length, libc::PROT_READ),
FunctionCode::MprotectW => self.mprotect(addr, length, libc::PROT_WRITE),
FunctionCode::MprotectRW => {
self.mprotect(addr, length, libc::PROT_READ | libc::PROT_WRITE)
}
FunctionCode::Mergeable => self.madvise(addr, length, libc::MADV_MERGEABLE),
FunctionCode::Unmergeable => self.madvise(addr, length, libc::MADV_UNMERGEABLE),
};
result.map(|_| PvmemcontrolResp::default())
}
fn handle_request(
&self,
PvmemcontrolReq {
func_code,
addr,
length,
arg,
}: PvmemcontrolReq,
) -> Result<PvmemcontrolResp, Error> {
let (func_code, addr, length, arg) = (
func_code.to_native(),
addr.to_native(),
length.to_native(),
arg.to_native(),
);
let resp_or_err = FunctionCode::try_from(func_code)
.map_err(|_| Error::UnknownFunctionCode(func_code))
.and_then(|func_code| self.process_request(func_code, addr, length, arg));
let resp = match resp_or_err {
Ok(resp) => resp,
Err(e) => match e {
Error::InvalidArgument(arg) => PvmemcontrolResp {
ret_errno: (libc::EINVAL as u32).into(),
ret_code: (arg as u32).into(),
..Default::default()
},
Error::LibcFail(err) => PvmemcontrolResp {
ret_errno: (err.raw_os_error().unwrap_or(libc::EFAULT) as u32).into(),
ret_code: 0u32.into(),
..Default::default()
},
Error::UnknownFunctionCode(func_code) => PvmemcontrolResp {
ret_errno: (libc::EOPNOTSUPP as u32).into(),
ret_code: (func_code as u32).into(),
..Default::default()
},
Error::GuestMemory(err) => {
warn!("{}", err);
PvmemcontrolResp {
ret_errno: (libc::EINVAL as u32).into(),
ret_code: (func_code as u32).into(),
..Default::default()
}
}
// device error, stop responding
other => return Err(other),
},
};
Ok(resp)
}
fn handle_pvmemcontrol_request(&self, guest_addr: GuestAddress) {
let request: PvmemcontrolReq = if let Ok(x) = self.mem.memory().read_obj(guest_addr) {
x
} else {
warn!("cannot read from guest address {:#x}", guest_addr.0);
return;
};
let response: PvmemcontrolResp = match self.handle_request(request) {
Ok(x) => x,
Err(e) => {
warn!("cannot process request {:?} with error {}", request, e);
return;
}
};
if self.mem.memory().write_obj(response, guest_addr).is_err() {
warn!("cannot write to guest address {:#x}", guest_addr.0);
}
}
fn handle_guest_write(&self, offset: u64, data: &[u8]) {
if offset as usize != std::mem::offset_of!(PvmemcontrolTransport, command) {
if data.len() != 4 && data.len() != 8 {
warn!("guest write is not 4 or 8 bytes long");
return;
}
self.dev.write().unwrap().write_transport(offset, data);
return;
}
let data = if data.len() == 4 {
let mut d = [0u8; 4];
d.iter_mut()
.zip(data.iter())
.for_each(|(d, data)| *d = *data);
d
} else {
warn!("guest write with non u32 at command register");
return;
};
let data_cmd = u32::from_le_bytes(data);
let command = PvmemcontrolTransportCommand::try_from(data_cmd);
match command {
Ok(command) => self.dev.write().unwrap().run_command(&self.mem, command),
Err(_) => {
GuestConnection::try_from(data_cmd)
.and_then(|conn| {
self.dev
.read()
.unwrap()
.find_connection(conn)
.ok_or(Error::InvalidConnection(conn.command))
})
.map(|gpa| self.handle_pvmemcontrol_request(gpa))
.unwrap_or_else(|err| warn!("{:?}", err));
}
}
}
fn handle_guest_read(&self, offset: u64, data: &mut [u8]) {
self.dev.read().unwrap().read_transport(offset, data)
}
}
impl PvmemcontrolDevice {
pub fn make_device(
id: String,
mem: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
) -> (PvmemcontrolPciDevice, PvmemcontrolBusDevice) {
let dev = RwLock::new(PvmemcontrolDevice::error());
let mut configuration = PciConfiguration::new(
PVMEMCONTROL_VENDOR_ID,
PVMEMCONTROL_DEVICE_ID,
0x1,
PciClassCode::BaseSystemPeripheral,
&PvmemcontrolSubclass::Other,
None,
PciHeaderType::Device,
PVMEMCONTROL_SUBSYSTEM_VENDOR_ID,
PVMEMCONTROL_SUBSYSTEM_ID,
None,
None,
);
let command: [u8; 2] = [0x03, 0x01]; // memory, io, SERR#
configuration.write_config_register(1, 0, &command);
(
PvmemcontrolPciDevice {
id,
configuration,
bar_regions: Vec::new(),
},
PvmemcontrolBusDevice { mem, dev },
)
}
}
impl PciDevice for PvmemcontrolPciDevice {
fn write_config_register(
&mut self,
reg_idx: usize,
offset: u64,
data: &[u8],
) -> Option<Arc<Barrier>> {
self.configuration
.write_config_register(reg_idx, offset, data);
None
}
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
self.configuration.read_config_register(reg_idx)
}
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn id(&self) -> Option<String> {
Some(self.id.clone())
}
fn detect_bar_reprogramming(
&mut self,
reg_idx: usize,
data: &[u8],
) -> Option<BarReprogrammingParams> {
self.configuration.detect_bar_reprogramming(reg_idx, data)
}
fn allocate_bars(
&mut self,
_allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new();
let region_type = PciBarRegionType::Memory32BitRegion;
let bar_id = 0;
let region_size = PVMEMCONTROL_DEVICE_MMIO_SIZE;
let restoring = resources.is_some();
let bar_addr = mmio32_allocator
.allocate(None, region_size, Some(PVMEMCONTROL_DEVICE_MMIO_ALIGN))
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
let bar = PciBarConfiguration::default()
.set_index(bar_id as usize)
.set_address(bar_addr.raw_value())
.set_size(region_size)
.set_region_type(region_type)
.set_prefetchable(PciBarPrefetchable::NotPrefetchable);
if !restoring {
self.configuration
.add_pci_bar(&bar)
.map_err(|e| PciDeviceError::IoRegistrationFailed(bar_addr.raw_value(), e))?;
}
bars.push(bar);
self.bar_regions.clone_from(&bars);
Ok(bars)
}
fn free_bars(
&mut self,
_allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) {
mmio32_allocator.free(GuestAddress(bar.addr()), bar.size())
}
Ok(())
}
fn move_bar(&mut self, old_base: u64, new_base: u64) -> result::Result<(), io::Error> {
for bar in self.bar_regions.iter_mut() {
if bar.addr() == old_base {
*bar = bar.set_address(new_base);
}
}
Ok(())
}
}
impl Pausable for PvmemcontrolPciDevice {
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
Ok(())
}
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
Ok(())
}
}
impl Snapshottable for PvmemcontrolPciDevice {
fn id(&self) -> String {
self.id.clone()
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let mut snapshot = Snapshot::new_from_state(&())?;
// Snapshot PciConfiguration
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
Ok(snapshot)
}
}
impl Transportable for PvmemcontrolPciDevice {}
impl Migratable for PvmemcontrolPciDevice {}
impl BusDeviceSync for PvmemcontrolBusDevice {
fn read(&self, _base: u64, offset: u64, data: &mut [u8]) {
self.handle_guest_read(offset, data)
}
fn write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
self.handle_guest_write(offset, data);
None
}
}

View File

@@ -450,7 +450,7 @@ impl BusDevice for Tpm {
);
}
_ => {
error!("Invalid value passed to CRTL_REQ register");
error!("Invalid value passed to CTRL_REQ register");
return None;
}
},

View File

@@ -270,7 +270,7 @@ definition in XML format:
### Command Line Interface
The Cloud Hypervisor Command Line Interface (CLI) can only be used for launching
the Cloud Hypervisor binary, i.e. it can not be used for controlling the VMM or
the Cloud Hypervisor binary, i.e. it cannot be used for controlling the VMM or
the launched VM once they're up and running.
If you want to inspect the VMM, or control the VM after launching Cloud

View File

@@ -159,10 +159,10 @@ as we might need to update the direct kernel boot command line, replacing
Update all references to the previous image name to the new one.
## NVIDIA image for VFIO baremetal CI
## NVIDIA image for VFIO bare-metal CI
Here we are going to describe how to create a cloud image that contains the
necessary NVIDIA drivers for our VFIO baremetal CI.
necessary NVIDIA drivers for our VFIO bare-metal CI.
### Download base image

View File

@@ -2,7 +2,7 @@
Cloud Hypervisor uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz) for fuzzing individual components.
The fuzzers are are in the `fuzz/fuzz_targets` directory
The fuzzers are in the `fuzz/fuzz_targets` directory
## Preparation

View File

@@ -53,7 +53,7 @@ On-line CPU(s) list: 0-7
After a reboot the added CPUs will remain.
Removing CPUs works similarly by reducing the number in the "desired_vcpus" field of the reisze API. The CPUs will be automatically offlined inside the guest so there is no need to run any commands inside the guest:
Removing CPUs works similarly by reducing the number in the "desired_vcpus" field of the resize API. The CPUs will be automatically offlined inside the guest so there is no need to run any commands inside the guest:
```shell
./ch-remote --api-socket=/tmp/ch-socket resize --cpus 2

View File

@@ -39,7 +39,7 @@ Another reason for having a virtual IOMMU is to allow passing physical devices
from the host through multiple layers of virtualization. Let's take as example
a system with a physical IOMMU running a VM with a virtual IOMMU. The
implementation of the virtual IOMMU is responsible for updating the physical
DMA Remapping table (DMAR) everytime the DMA mapping changes. This must happen
DMA Remapping table (DMAR) every time the DMA mapping changes. This must happen
through the VFIO framework on the host as this is the only userspace interface
to interact with a physical IOMMU.
@@ -124,7 +124,7 @@ On AArch64 architecture, the virtual IOMMU can still be used even if ACPI is not
enabled. But the effect is different with what the aforementioned test showed.
When ACPI is disabled, virtual IOMMU is supported through Flattened Device Tree
(FDT). In this case, the guest kernel can not tell which device should be
(FDT). In this case, the guest kernel cannot tell which device should be
IOMMU-attached and which should not. No matter how many devices you attached to
the virtual IOMMU by setting `iommu=on` option, all the devices on the PCI bus
will be attached to the virtual IOMMU (except the IOMMU itself). Each of the

105
docs/landlock.md Normal file
View File

@@ -0,0 +1,105 @@
# Sandboxing using Landlock
Landlock is a lightweight mechanism to allow unprivileged applications to
sandbox themselves.
During initial stages of running, applications can define the set of resources
(mostly files) they need to access during their lifetime. All such rules are
used to create a ruleset. Once the ruleset is applied, the process cannot access
any resources outside of the ruleset during its lifetime, even if it were
compromised.
Under the scope of `read` and `write` access, Landlock currently allows some
additional accesses (eg: for now, access to extended file attributes is always
allowed). Eventually, Landlock will only allow accesses similar to Unix
permissions.
## Host Setup
Landlock should be enabled in Host kernel to use it with cloud-hypervisor.
Please following [Kernel-Support](https://docs.kernel.org/userspace-api/landlock.html#kernel-support) link to enable Landlock on Host kernel.
Landlock support can be checked with following command:
```
$ sudo dmesg | grep -w landlock
[ 0.000000] landlock: Up and running.
```
Linux kernel confirms Landlock support with above message in dmesg.
## Enable Landlock
At the time of enabling Landlock, Cloud-Hypervisor process needs the complete
list of files it accesses over its lifetime. So, Landlock is enabled `vm_create`
stage of guest boot.
### Command Line
Append `--landlock` to Cloud-Hypervisor's command line to enable Landlock
support.
If you expect guest to access additional paths after it boots
(ex: during hotplug), those paths can be passed using `--landlock-rules` command
line parameter.
### API
Landlock can also be enabled during `vm.create` request by passing a config like below:
```
{
...
"landlock_enable": true,
"landlock_rules": [
{
"path": "/tmp/disk1",
"access": "rw"
},
{
"path": "/tmp/disk2",
"access": "rw"
}
]
...
}
```
## Usage Examples
To enable Landlock:
```
./cloud-hypervisor \
--kernel ./linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--cmdline "console=hvc0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--landlock
```
Hotplugging any new file-backed resources to above guest will result in
**Permission Denied** error.
To enable Landlock with hotplug support:
```
./cloud-hypervisor \
--api-socket /tmpXXXX/ch.socket \
--kernel ./linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--cmdline "console=hvc0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--landlock \
--landlock-rules path="/path/to/hotplug1",access="rw" path="/path/to/hotplug2",access="rw"
./ch-remote --api-socket /tmpXXXX/ch.socket \
add-disk "path=/path/to/hotplug/blk.raw"
```
`--landlock-rules` accepts file or directory paths among its options.
# References
* https://landlock.io/

View File

@@ -466,7 +466,7 @@ List of virtual CPUs attached to the guest NUMA node identified by the
`guest_numa_id` option. This allows for describing a list of CPUs which
must be seen by the guest as belonging to the NUMA node `guest_numa_id`.
One can use this option for a fine grained description of the NUMA topology
One can use this option for a fine-grained description of the NUMA topology
regarding the CPUs associated with it, which might help the guest run more
efficiently.
@@ -573,7 +573,7 @@ _Example_
### PCI bus
Cloud Hypervisor supports guests with one or more PCI segments. The default PCI segment always
has affinity to NUMA node 0. Be default, all other PCI segments have afffinity to NUMA node 0.
has affinity to NUMA node 0. Be default, all other PCI segments have affinity to NUMA node 0.
The user may configure the NUMA affinity for any additional PCI segments.
_Example_

View File

@@ -8,6 +8,8 @@ e.g. `dev_cli.sh`. The only prerequisite is [Docker installation](https://docs.d
Please note that upon its first invocation, this script will pull a
fairly large container image.
## Run the Performance Tests
To generate metrics data for all available performance tests (including
boot time, block I/O throughput, and network throughput & latency) and
output the result into a json file:
@@ -27,3 +29,92 @@ To generate metrics data for selected performance tests, e.g. boot time only:
```
$ ./scripts/dev_cli.sh tests --metrics -- -- --report-file /tmp/metrics.json --test-filter boot_time
```
To set custom timeout or test iterations for all performance tests:
```
$ ./scripts/dev_cli.sh tests --metrics -- -- --timeout 5 --iterations 10
```
## Performance Tests Details
The following table lists the supported performance tests with default
timeout and number of iterations. The `timeout` defines the maximum
execution time of each test for each iteration. The `iteration` defines
how many times a test needs to be executed to generate the final metrics
data.
| **Type** | **Metric** | **Timeout(s)** | **Iterations** |
|------------|--------------------------------------------|----------------|----------------|
| Boot Time | boot_time_ms | 2 | 10 |
| | boot_time_pmem_ms | 2 | 10 |
| | boot_time_16_vcpus_ms | 2 | 10 |
| | boot_time_16_vcpus_pmem_ms | 2 | 10 |
| Virtio Net | virtio_net_latency_us | 10 | 5 |
| | virtio_net_throughput_single_queue_rx_gbps | 10 | 5 |
| | virtio_net_throughput_single_queue_tx_gbps | 10 | 5 |
| | virtio_net_throughput_multi_queue_rx_gbps | 10 | 5 |
| | virtio_net_throughput_multi_queue_tx_gbps | 10 | 5 |
| Block | block_read_MiBps | 10 | 5 |
| | block_write_MiBps | 10 | 5 |
| | block_random_read_MiBps | 10 | 5 |
| | block_random_write_MiBps | 10 | 5 |
| | block_multi_queue_read_MiBps | 10 | 5 |
| | block_multi_queue_write_MiBps | 10 | 5 |
| | block_multi_queue_random_read_MiBps | 10 | 5 |
| | block_multi_queue_random_write_MiBps | 10 | 5 |
| | block_read_IOPS | 10 | 5 |
| | block_write_IOPS | 10 | 5 |
| | block_random_read_IOPS | 10 | 5 |
| | block_random_write_IOPS | 10 | 5 |
| | block_multi_queue_read_IOPS | 10 | 5 |
| | block_multi_queue_write_IOPS | 10 | 5 |
| | block_multi_queue_random_read_IOPS | 10 | 5 |
| | block_multi_queue_random_write_IOPS | 10 | 5 |
| Other | restore_latency_time_ms | 2 | 10 |
## Output Format
Performance-metrics output the result into a json file if `report-file`
param is set. The fields included in JSON include:
| Field Name | Content |
|--------------------|------------------------------------------|
| git_human_readable | Recent tag information of git repository |
| git_revision | Commit id of HEAD |
| git_commit_date | Commit date of HEAD |
| date | Date for executing the program |
| results | A list of metrics |
## Example
Here is an example of generating metrics data for the boot time using
`pmem`:
```bash
$ ./scripts/dev_cli.sh tests --metrics -- -- --test-filter boot_time_pmem_ms
```
Here is a sample output:
```json
{
"git_human_readable": "v40.0",
"git_revision": "e9b263975786abbf895469b93dfc00f21ce39a88",
"git_commit_date": "Fri Jun 21 08:40:44 2024 +0000",
"date": "Tue Jul 16 16:35:29 UTC 2024",
"results": [
{
"name": "boot_time_pmem_ms",
"mean": 105.9461,
"std_dev": 7.140993312558129,
"max": 120.01499999999999,
"min": 92.37600000000002
}
]
}
```
Note that the metrics data above is for illustration purpose only and
does not represent the actual performance of Cloud Hypervisor on your
system.

2
docs/releases.md Executable file → Normal file
View File

@@ -95,7 +95,7 @@ E - EOL
```
### LTS Stablity Considerations
### LTS Stability Considerations
An LTS release is just a `MAJOR` release for which point releases are made for
longer following the same rules for what can be backported to a `POINT` release.

View File

@@ -63,7 +63,7 @@ component in the state it was left before the snapshot occurred.
## Restore a Cloud Hypervisor VM
Given that one has access to an existing snapshot in `/home/foo/snapshot`,
it is possible to create a new VM based on this snapshot with the following
it is possible to create a new VM based on this snapshot with the following
command:
```bash
@@ -93,6 +93,21 @@ start using it.
At this point, the VM is fully restored and is identical to the VM which was
snapshot earlier.
## Restore a VM with new Net FDs
For a VM created with FDs explicitly passed to NetConfig, a set of valid FDs
need to be provided along with the VM restore command in the following syntax:
```bash
# First terminal
./cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock
# Second terminal
./ch-remote --api-socket=/tmp/cloud-hypervisor.sock restore source_url=file:///home/foo/snapshot net_fds=[net1@[23,24],net2@[25,26]]
```
In the example above, the net device with id `net1` will be backed by FDs '23'
and '24', and the net device with id `net2` will be backed by FDs '25' and '26'
from the restored VM.
## Limitations
VFIO devices and Intel SGX are out of scope.

View File

@@ -37,6 +37,6 @@ generating traces of the boot. These can be relocated for focus tracing on a
narrow part of the code base.
A `tracer::trace_point!()` macro is also provided for an instantaneous trace
point however this is not in use in the code base currently nor is handled by
point however this is neither in use in the code base currently nor is handled by
the visualisation script due to the difficulty in representation in the SVG.

View File

@@ -1,12 +1,12 @@
[package]
name = "event_monitor"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
name = "event_monitor"
version = "0.1.0"
[dependencies]
flume = "0.11.0"
libc = "0.2.153"
libc = "0.2.155"
once_cell = "1.19.0"
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_json = "1.0.120"

432
fuzz/Cargo.lock generated
View File

@@ -12,47 +12,48 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.13"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys",
@@ -60,16 +61,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.82"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
name = "api_client"
version = "0.1.0"
dependencies = [
"vmm-sys-util",
]
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "arbitrary"
@@ -105,9 +99,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bitflags"
@@ -117,9 +111,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block"
@@ -127,7 +121,6 @@ version = "0.1.0"
dependencies = [
"byteorder",
"crc-any",
"io-uring",
"libc",
"log",
"remain",
@@ -156,12 +149,13 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.92"
version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
checksum = "5fb8dd288a69fc53a1996d7ecfbf4a20d59065bff137ce7e56bbd620de191189"
dependencies = [
"jobserver",
"libc",
"shlex",
]
[[package]]
@@ -172,61 +166,36 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.4"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim 0.11.1",
"strsim",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "cloud-hypervisor"
version = "38.0.0"
dependencies = [
"anyhow",
"api_client",
"clap",
"epoll",
"event_monitor",
"hypervisor",
"libc",
"log",
"option_parser",
"seccompiler",
"serde_json",
"signal-hook",
"thiserror",
"tpm",
"tracer",
"vm-memory",
"vmm",
"vmm-sys-util",
]
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "cloud-hypervisor-fuzz"
version = "0.0.0"
dependencies = [
"block",
"cloud-hypervisor",
"devices",
"epoll",
"libc",
@@ -248,24 +217,24 @@ dependencies = [
[[package]]
name = "colorchoice"
version = "1.0.0"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "crc-any"
version = "2.4.4"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c01a5e1f881f6fb6099a7bdf949e946719fd4f1fefa56264890574febf0eb6d0"
checksum = "a62ec9ff5f7965e4d7280bd5482acd20aadb50d632cf6c1d74493856b011fa73"
dependencies = [
"debug-helper",
]
[[package]]
name = "darling"
version = "0.20.8"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
@@ -273,23 +242,23 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.20.8"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.10.0",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.8"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
@@ -309,12 +278,13 @@ dependencies = [
"acpi_tables",
"anyhow",
"arch",
"bitflags 2.5.0",
"bitflags 2.6.0",
"byteorder",
"event_monitor",
"hypervisor",
"libc",
"log",
"num_enum",
"pci",
"serde",
"thiserror",
@@ -326,16 +296,42 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "enumflags2"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d"
dependencies = [
"enumflags2_derive",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "epoll"
version = "4.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74351c3392ea1ff6cd2628e0042d268ac2371cb613252ff383b6dfa50d22fa79"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"libc",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "event_monitor"
version = "0.1.0"
@@ -384,10 +380,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "getrandom"
version = "0.2.14"
name = "gdbstub"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
checksum = "6341b3480afbb34eaefc7f92713bc92f2d83e338aaa1c44192f9c2956f4a4903"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"log",
"managed",
"num-traits",
"paste",
]
[[package]]
name = "gdbstub_arch"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e3b1357bd3203fc09a6601327ae0ab38865d14231d0b65d3143f5762cc7977d"
dependencies = [
"gdbstub",
"num-traits",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"js-sys",
@@ -396,6 +416,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hypervisor"
version = "0.1.0"
@@ -421,15 +447,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "io-uring"
version = "0.6.3"
name = "indexmap"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9febecd4aebbe9c7c23c8e536e966805fdf09944c8a915e7991ee51acb67087"
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
dependencies = [
"bitflags 1.3.2",
"libc",
"equivalent",
"hashbrown",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.11"
@@ -438,9 +470,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jobserver"
version = "0.1.30"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"libc",
]
@@ -471,17 +503,28 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"kvm-bindings",
"libc",
"vmm-sys-util",
]
[[package]]
name = "libc"
version = "0.2.153"
name = "landlock"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "dafb8a4afee64f167eb2b52d32f0eea002e41a7a6450e68c799c8ec3a81a634c"
dependencies = [
"enumflags2",
"libc",
"thiserror",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libfuzzer-sys"
@@ -505,9 +548,9 @@ dependencies = [
[[package]]
name = "lock_api"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
@@ -515,9 +558,21 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.21"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "managed"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "micro_http"
@@ -563,6 +618,36 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "once_cell"
version = "1.19.0"
@@ -573,6 +658,12 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
name = "option_parser"
version = "0.1.0"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pci"
version = "0.1.0"
@@ -595,10 +686,19 @@ dependencies = [
]
[[package]]
name = "proc-macro2"
version = "1.0.81"
name = "proc-macro-crate"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@@ -625,9 +725,9 @@ dependencies = [
[[package]]
name = "remain"
version = "0.2.13"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad9f2390298a947ee0aa6073d440e221c0726188cfbcdf9604addb6ee393eb4a"
checksum = "46aef80f842736de545ada6ec65b81ee91504efd6853f4b96de7414c42ae7443"
dependencies = [
"proc-macro2",
"quote",
@@ -636,9 +736,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
@@ -657,18 +757,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.198"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.198"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
@@ -677,9 +777,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.115"
version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [
"itoa",
"ryu",
@@ -688,9 +788,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.8.0"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c85f8e96d1d6857f13768fcbd895fcb06225510022a2774ed8b5150581847b0"
checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857"
dependencies = [
"serde",
"serde_derive",
@@ -699,9 +799,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.8.0"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8b3a576c4eb2924262d5951a3b737ccaf16c931e39a2810c36f9a7e25575557"
checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350"
dependencies = [
"darling",
"proc-macro2",
@@ -713,6 +813,12 @@ dependencies = [
name = "serial_buffer"
version = "0.1.0"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.17"
@@ -747,12 +853,6 @@ dependencies = [
"lock_api",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
@@ -761,9 +861,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.58"
version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
@@ -772,24 +872,41 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.58"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
[[package]]
name = "toml_edit"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
dependencies = [
"indexmap",
"toml_datetime",
"winnow",
]
[[package]]
name = "tpm"
version = "0.1.0"
@@ -822,15 +939,15 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.8.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
dependencies = [
"getrandom",
]
@@ -878,11 +995,11 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
checksum = "6be08d1166d41a78861ad50212ab3f9eca0729c349ac3a7a8f557c62406b87cc"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"libc",
"vm-memory",
"vmm-sys-util",
@@ -929,9 +1046,9 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d"
checksum = "07d8406e7250c934462de585d8f2d2781c31819bca1fbb7c5e964ca6bbaabfe8"
dependencies = [
"log",
"virtio-bindings",
@@ -1006,7 +1123,7 @@ dependencies = [
"anyhow",
"arc-swap",
"arch",
"bitflags 2.5.0",
"bitflags 2.6.0",
"block",
"cfg-if",
"clap",
@@ -1014,7 +1131,10 @@ dependencies = [
"epoll",
"event_monitor",
"flume",
"gdbstub",
"gdbstub_arch",
"hypervisor",
"landlock",
"libc",
"linux-loader",
"log",
@@ -1150,13 +1270,14 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
@@ -1165,51 +1286,66 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr",
]
[[package]]
name = "zerocopy"
version = "0.7.32"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
@@ -1217,9 +1353,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -1,135 +1,133 @@
[package]
name = "cloud-hypervisor-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
edition = "2021"
name = "cloud-hypervisor-fuzz"
publish = false
version = "0.0.0"
[package.metadata]
cargo-fuzz = true
[features]
igvm = []
pvmemcontrol = []
[dependencies]
block = { path = "../block" }
devices = { path = "../devices" }
epoll = "4.3.3"
libc = "0.2.153"
libc = "0.2.155"
libfuzzer-sys = "0.4.7"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
linux-loader = { version = "0.11.0", features = ["bzimage", "elf", "pe"] }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
net_util = { path = "../net_util" }
once_cell = "1.19.0"
seccompiler = "0.4.0"
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.11.0"
vmm = { path = "../vmm" }
vmm-sys-util = "0.12.1"
virtio-queue = "0.12.0"
vm-device = { path = "../vm-device" }
vm-memory = "0.14.1"
vm-migration = { path = "../vm-migration" }
vm-device = { path = "../vm-device" }
vm-virtio = { path = "../vm-virtio" }
[dependencies.cloud-hypervisor]
path = ".."
vmm = { path = "../vmm", features = ["guest_debug"] }
vmm-sys-util = "0.12.1"
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
doc = false
name = "balloon"
path = "fuzz_targets/balloon.rs"
test = false
doc = false
[[bin]]
doc = false
name = "block"
path = "fuzz_targets/block.rs"
test = false
doc = false
[[bin]]
doc = false
name = "cmos"
path = "fuzz_targets/cmos.rs"
test = false
doc = false
[[bin]]
doc = false
name = "console"
path = "fuzz_targets/console.rs"
test = false
doc = false
[[bin]]
doc = false
name = "http_api"
path = "fuzz_targets/http_api.rs"
test = false
doc = false
[[bin]]
doc = false
name = "iommu"
path = "fuzz_targets/iommu.rs"
test = false
doc = false
[[bin]]
doc = false
name = "linux_loader"
path = "fuzz_targets/linux_loader.rs"
test = false
doc = false
[[bin]]
doc = false
name = "linux_loader_cmdline"
path = "fuzz_targets/linux_loader_cmdline.rs"
test = false
doc = false
[[bin]]
doc = false
name = "mem"
path = "fuzz_targets/mem.rs"
test = false
doc = false
[[bin]]
doc = false
name = "net"
path = "fuzz_targets/net.rs"
test = false
doc = false
[[bin]]
doc = false
name = "pmem"
path = "fuzz_targets/pmem.rs"
test = false
doc = false
[[bin]]
doc = false
name = "qcow"
path = "fuzz_targets/qcow.rs"
test = false
doc = false
[[bin]]
doc = false
name = "rng"
path = "fuzz_targets/rng.rs"
test = false
doc = false
[[bin]]
doc = false
name = "serial"
path = "fuzz_targets/serial.rs"
test = false
doc = false
[[bin]]
doc = false
name = "vhdx"
path = "fuzz_targets/vhdx.rs"
test = false
doc = false
[[bin]]
doc = false
name = "watchdog"
path = "fuzz_targets/watchdog.rs"
test = false
doc = false

View File

@@ -105,7 +105,7 @@ impl RequestHandler for StubApiRequestHandler {
Ok(())
}
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
#[cfg(target_arch = "x86_64")]
fn vm_coredump(&mut self, _: &str) -> Result<(), VmError> {
Ok(())
}
@@ -180,17 +180,20 @@ impl RequestHandler for StubApiRequestHandler {
vdpa: None,
vsock: None,
pvpanic: false,
#[cfg(feature = "pvmemcontrol")]
pvmemcontrol: None,
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
numa: None,
watchdog: false,
#[cfg(feature = "guest_debug")]
gdb: false,
pci_segments: None,
platform: None,
tpm: None,
preserved_fds: None,
landlock_enable: false,
landlock_rules: None,
})),
state: VmState::Running,
memory_actual_size: 0,

View File

@@ -1,39 +1,47 @@
[package]
name = "hypervisor"
version = "0.1.0"
authors = ["Microsoft Authors"]
edition = "2021"
license = "Apache-2.0 OR BSD-3-Clause"
name = "hypervisor"
version = "0.1.0"
[features]
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"]
sev_snp = ["igvm_parser", "igvm_defs"]
kvm = ["kvm-bindings", "kvm-ioctls", "vfio-ioctls/kvm"]
mshv = ["iced-x86", "mshv-bindings", "mshv-ioctls", "vfio-ioctls/mshv"]
sev_snp = ["igvm", "igvm_defs"]
tdx = []
[dependencies]
anyhow = "1.0.81"
anyhow = "1.0.86"
byteorder = "1.5.0"
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
libc = "0.2.153"
log = "0.4.21"
igvm = { version = "0.3.3", optional = true }
igvm_defs = { version = "0.3.1", optional = true }
kvm-bindings = { version = "0.8.1", optional = true, features = ["serde"] }
kvm-ioctls = { version = "0.17.0", optional = true }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_with = { version = "3.7.0", default-features = false, features = ["macros"] }
libc = "0.2.155"
log = "0.4.22"
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", features = [
"fam-wrappers",
"with-serde",
], optional = true }
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", tag = "v0.2.0", optional = true }
serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_with = { version = "3.9.0", default-features = false, features = [
"macros",
] }
thiserror = "1.0.62"
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }
vm-memory = { version = "0.14.1", features = [
"backend-atomic",
"backend-mmap",
] }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
thiserror = "1.0.58"
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
default-features = false
features = ["decoder", "fast_fmt", "instr_info", "op_code_info", "std"]
optional = true
version = "1.21.0"
default-features = false
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
[dev-dependencies]
env_logger = "0.11.3"

View File

@@ -5,15 +5,19 @@
use crate::{CpuState, GicState, HypervisorDeviceError, HypervisorVmError};
use std::any::Any;
use std::result;
use thiserror::Error;
/// Errors thrown while setting up the VGIC.
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum Error {
/// Error while calling KVM ioctl for setting up the global interrupt controller.
#[error("Failed creating GIC device: {0}")]
CreateGic(HypervisorVmError),
/// Error while setting device attributes for the GIC.
#[error("Failed setting device attributes for the GIC: {0}")]
SetDeviceAttribute(HypervisorDeviceError),
/// Error while getting device attributes for the GIC.
#[error("Failed getting device attributes for the GIC: {0}")]
GetDeviceAttribute(HypervisorDeviceError),
}
pub type Result<T> = result::Result<T, Error>;

View File

@@ -137,14 +137,6 @@ pub trait PlatformEmulator {
///
fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError>;
/// Translate a guest virtual address into a physical one
///
/// # Arguments
///
/// * `gva` - Guest virtual address to translate.
///
fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError>;
/// Fetch instruction bytes from memory.
///
/// # Arguments

View File

@@ -13,6 +13,7 @@ pub mod cmp;
pub mod mov;
pub mod movs;
pub mod or;
pub mod stos;
fn get_op<T: CpuStateManager>(
insn: &Instruction,

View File

@@ -40,7 +40,7 @@ macro_rules! movs {
let len = std::mem::size_of::<$bound>();
while count > 0 {
let mut memory: [u8; 4] = [0; 4];
let mut memory: [u8; 8] = [0; 8];
let src = state
.linearize(Register::DS, rsi, false)
@@ -83,6 +83,11 @@ macro_rules! movs {
};
}
pub struct Movsq_m64_m64;
impl<T: CpuStateManager> InstructionHandler<T> for Movsq_m64_m64 {
movs!(u64);
}
pub struct Movsd_m32_m32;
impl<T: CpuStateManager> InstructionHandler<T> for Movsd_m32_m32 {
movs!(u32);
@@ -103,6 +108,40 @@ mod tests {
use super::*;
use crate::arch::x86::emulator::mock_vmm::*;
#[test]
fn test_rep_movsq_m64_m64() {
let ip: u64 = 0x1000;
let memory: [u8; 32] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0xdd, 0xcc, 0xbb, 0xaa, // 0xaabbccdd
0xa5, 0x5a, 0xa5, 0x5a, // 0x5aa55aa5
0xcd, 0xcd, 0xcd, 0xcd, // 0xcdcdcdcd
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0xf3, 0x48, 0xa5]; // rep movsq
let regs = vec![
(Register::ECX, 2),
(Register::ESI, 0),
(Register::EDI, 0x10),
];
let mut data = [0u8; 8];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x10, &mut data).unwrap();
assert_eq!(0xaabbccdd12345678, <u64>::from_le_bytes(data));
vmm.read_memory(0x18, &mut data).unwrap();
assert_eq!(0xcdcdcdcd5aa55aa5, <u64>::from_le_bytes(data));
// The rest should be default value 0 from MockVmm
vmm.read_memory(0x20, &mut data).unwrap();
assert_eq!(0x0, <u64>::from_le_bytes(data));
}
#[test]
fn test_rep_movsd_m32_m32() {
let ip: u64 = 0x1000;

View File

@@ -0,0 +1,236 @@
//
// Copyright © 2024 Microsoft
//
// SPDX-License-Identifier: Apache-2.0
//
#![allow(non_camel_case_types)]
//
// STOS - Store String
//
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::DF;
macro_rules! stos {
($bound:ty) => {
fn emulate(
&self,
insn: &Instruction,
state: &mut T,
platform: &mut dyn PlatformEmulator<CpuState = T>,
) -> Result<(), EmulationError<Exception>> {
let mut count: u64 = if insn.has_rep_prefix() {
state
.read_reg(Register::ECX)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?
} else {
1
};
let rax = state
.read_reg(Register::RAX)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let mut rdi = state
.read_reg(Register::RDI)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let df = (state.flags() & DF) != 0;
let len = std::mem::size_of::<$bound>();
let rax_bytes = rax.to_le_bytes();
while count > 0 {
let dst = state
.linearize(Register::ES, rdi, true)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
platform
.write_memory(dst, &rax_bytes[0..len])
.map_err(EmulationError::PlatformEmulationError)?;
if df {
rdi = rdi.wrapping_sub(len as u64);
} else {
rdi = rdi.wrapping_add(len as u64);
}
count -= 1;
}
if insn.has_rep_prefix() {
state
.write_reg(Register::ECX, 0)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
}
Ok(())
}
};
}
pub struct Stosq_m64_RAX;
impl<T: CpuStateManager> InstructionHandler<T> for Stosq_m64_RAX {
stos!(u64);
}
pub struct Stosd_m32_EAX;
impl<T: CpuStateManager> InstructionHandler<T> for Stosd_m32_EAX {
stos!(u32);
}
pub struct Stosw_m16_AX;
impl<T: CpuStateManager> InstructionHandler<T> for Stosw_m16_AX {
stos!(u16);
}
pub struct Stosb_m8_AL;
impl<T: CpuStateManager> InstructionHandler<T> for Stosb_m8_AL {
stos!(u8);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::arch::x86::emulator::mock_vmm::*;
#[test]
fn test_rep_stosb() {
let ip: u64 = 0x1000;
let memory: [u8; 12] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0xdd, 0xcc, 0xbb, 0xaa, // 0xaabbccdd
0xa5, 0x5a, 0xa5, 0x5a, // 0x5aa55aa5
];
let insn = [0xf3, 0xaa]; // rep stosb
let regs = vec![
(Register::ECX, 3),
(Register::EDI, 0x0),
(Register::RAX, 0x123456ff),
];
let mut data = [0u8; 4];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0, &mut data).unwrap();
assert_eq!(0x12ffffff, <u32>::from_le_bytes(data));
vmm.read_memory(4, &mut data).unwrap();
assert_eq!(0xaabbccdd, <u32>::from_le_bytes(data));
vmm.read_memory(8, &mut data).unwrap();
assert_eq!(0x5aa55aa5, <u32>::from_le_bytes(data));
}
#[test]
fn test_stosw() {
let ip: u64 = 0x1000;
let memory: [u8; 4] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
];
let insn = [0x66, 0xab]; // stosw
let regs = vec![(Register::EDI, 0x1), (Register::AX, 0xaabb)];
let mut data = [0u8; 4];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x0, &mut data).unwrap();
assert_eq!(0x12aabb78, <u32>::from_le_bytes(data));
// The rest should be default value 0 from MockVmm
vmm.read_memory(0x4, &mut data).unwrap();
assert_eq!(0x0, <u32>::from_le_bytes(data));
vmm.read_memory(0x8 + 8, &mut data).unwrap();
assert_eq!(0x0, <u32>::from_le_bytes(data));
}
#[test]
fn test_rep_stosw() {
let ip: u64 = 0x1000;
let memory: [u8; 8] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0x66, 0xf3, 0xab]; // rep stosw
let regs = vec![
(Register::ECX, 2),
(Register::EDI, 0x2),
(Register::AX, 0xaabb),
];
let mut data = [0u8; 4];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x0, &mut data).unwrap();
assert_eq!(0xaabb5678, <u32>::from_le_bytes(data));
vmm.read_memory(0x4, &mut data).unwrap();
assert_eq!(0x0000aabb, <u32>::from_le_bytes(data));
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0x0, <u32>::from_le_bytes(data));
}
#[test]
fn test_rep_stosd() {
let ip: u64 = 0x1000;
let memory: [u8; 12] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0xf3, 0xab]; // rep stosd
let regs = vec![
(Register::ECX, 2),
(Register::EDI, 0x8),
(Register::EAX, 0xaabbccdd),
];
let mut data = [0u8; 4];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
// Go backwards this time
let mut state = vmm.cpu_state(0).unwrap();
state.set_flags(state.flags() | DF);
vmm.set_cpu_state(0, state).unwrap();
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x0, &mut data).unwrap();
assert_eq!(0x12345678, <u32>::from_le_bytes(data));
vmm.read_memory(0x4, &mut data).unwrap();
assert_eq!(0xaabbccdd, <u32>::from_le_bytes(data));
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0xaabbccdd, <u32>::from_le_bytes(data));
vmm.read_memory(0xc, &mut data).unwrap();
assert_eq!(0x0, <u32>::from_le_bytes(data));
}
#[test]
fn test_rep_stosq() {
let ip: u64 = 0x1000;
let memory: [u8; 8] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0xf3, 0x48, 0xab]; // rep stosq
let regs = vec![
(Register::ECX, 2),
(Register::RDI, 0x0),
(Register::RAX, 0x11223344aabbccdd),
];
let mut data = [0u8; 8];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x0, &mut data).unwrap();
assert_eq!(0x11223344aabbccdd, <u64>::from_le_bytes(data));
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0x11223344aabbccdd, <u64>::from_le_bytes(data));
vmm.read_memory(0x10, &mut data).unwrap();
assert_eq!(0x0, <u64>::from_le_bytes(data));
}
}

View File

@@ -135,7 +135,7 @@ pub trait CpuStateManager: Clone {
.checked_add(segment_register.base)
.ok_or_else(|| {
PlatformError::InvalidAddress(anyhow!(
"Logical address {:#x} can not be linearized with segment {:#x?}",
"Logical address {:#x} cannot be linearized with segment {:#x?}",
logical_addr,
segment_register
))
@@ -148,7 +148,7 @@ pub trait CpuStateManager: Clone {
// Must not write to a read-only segment.
if segment_type_ro(segment_type) && write {
return Err(PlatformError::InvalidAddress(anyhow!(
"Can not write to a read-only segment"
"Cannot write to a read-only segment"
)));
}
@@ -532,11 +532,17 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
(mov, Mov_moffs64_RAX),
(mov, Mov_RAX_moffs64),
// MOVS
(movs, Movsq_m64_m64),
(movs, Movsd_m32_m32),
(movs, Movsw_m16_m16),
(movs, Movsb_m8_m8),
// OR
(or, Or_rm8_r8)
(or, Or_rm8_r8),
// STOS
(stos, Stosb_m8_AL),
(stos, Stosw_m16_AX),
(stos, Stosd_m32_EAX),
(stos, Stosq_m64_RAX)
);
handler
@@ -561,7 +567,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
decoder.set_ip(state.ip());
while decoder.can_decode() && !stop_emulation {
while !stop_emulation {
decoder.decode_out(&mut insn);
if decoder.last_error() == DecoderError::NoMoreBytes {
@@ -588,6 +594,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
// Once we have the new stream, we must create a new decoder
// and emulate one last instruction from the last decoded IP.
decoder = Decoder::new(64, &fetched_insn_stream, DecoderOptions::NONE);
decoder.set_ip(last_decoded_ip);
decoder.decode_out(&mut insn);
if decoder.last_error() != DecoderError::None {
return Err(EmulationError::InstructionFetchingError(anyhow!(
@@ -595,8 +602,6 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
insn_format!(insn)
)));
}
stop_emulation = true;
}
// Emulate the decoded instruction
@@ -751,10 +756,6 @@ mod mock_vmm {
Ok(())
}
fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError> {
Ok(gva)
}
fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError> {
let rip = self
.state
@@ -771,12 +772,77 @@ mod tests {
use super::*;
use crate::arch::x86::emulator::mock_vmm::*;
#[test]
// Emulate executing an empty stream. Instructions should be fetched from
// memory.
//
// mov rax, 0x1000
// mov rbx, qword ptr [rax+10h]
fn test_empty_instruction_stream() {
let target_rax: u64 = 0x1000;
let target_rbx: u64 = 0x1234567812345678;
let ip: u64 = 0x1000;
let cpu_id = 0;
let memory = [
// Code at IP
0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
// Padding
0x00, 0x00, 0x00, 0x00, 0x00, // Padding is all zeroes
// Data at IP + 0x10 (0x1234567812345678 in LE)
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
];
let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
assert!(vmm.emulate_insn(cpu_id, &[], Some(2)).is_ok());
let rax: u64 = vmm
.cpu_state(cpu_id)
.unwrap()
.read_reg(Register::RAX)
.unwrap();
assert_eq!(rax, target_rax);
let rbx: u64 = vmm
.cpu_state(cpu_id)
.unwrap()
.read_reg(Register::RBX)
.unwrap();
assert_eq!(rbx, target_rbx);
}
#[test]
// Emulate executing an empty stream. Instructions should be fetched from
// memory. The emulation should abort.
//
// mov rax, 0x1000
// mov rbx, qword ptr [rax+10h]
// ... garbage ...
fn test_empty_instruction_stream_bad() {
let ip: u64 = 0x1000;
let cpu_id = 0;
let memory = [
// Code at IP
0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
// Padding
0xff, 0xff, 0xff, 0xff, 0xff, // Garbage
// Data at IP + 0x10 (0x1234567812345678 in LE)
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
];
let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
assert!(vmm.emulate_insn(cpu_id, &[], None).is_err());
}
#[test]
// Emulate truncated instruction stream, which should cause a fetch.
//
// mov rax, 0x1000
// mov rbx, qword ptr [rax+10h]
// Test with a first instruction truncated.
fn test_fetch_first_instruction() {
let target_rax: u64 = 0x1000;
let ip: u64 = 0x1000;
let cpu_id = 0;
let memory = [
@@ -801,7 +867,7 @@ mod tests {
.unwrap()
.read_reg(Register::RAX)
.unwrap();
assert_eq!(rax, ip);
assert_eq!(rax, target_rax);
}
#[test]
@@ -839,6 +905,52 @@ mod tests {
assert_eq!(rbx, target_rax);
}
#[test]
// Emulate only one instruction.
//
// mov rax, 0x1000
// mov rbx, qword ptr [rax+10h]
// The emulation should stop after the first instruction.
fn test_emulate_one_instruction() {
let target_rax: u64 = 0x1000;
let ip: u64 = 0x1000;
let cpu_id = 0;
let memory = [
// Code at IP
0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
// Padding
0x00, 0x00, 0x00, 0x00, 0x00, // Padding is all zeroes
// Data at IP + 0x10 (0x1234567812345678 in LE)
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
];
let insn = [
0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
];
let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
assert!(vmm.emulate_insn(cpu_id, &insn, Some(1)).is_ok());
let new_ip: u64 = vmm.cpu_state(cpu_id).unwrap().ip();
assert_eq!(new_ip, ip + 0x7 /* length of mov rax,0x1000 */);
let rax: u64 = vmm
.cpu_state(cpu_id)
.unwrap()
.read_reg(Register::RAX)
.unwrap();
assert_eq!(rax, target_rax);
// The second instruction is not executed so RBX should be zero.
let rbx: u64 = vmm
.cpu_state(cpu_id)
.unwrap()
.read_reg(Register::RBX)
.unwrap();
assert_eq!(rbx, 0);
}
#[test]
// Emulate truncated instruction stream, which should cause a fetch.
//

View File

@@ -53,7 +53,6 @@ pub enum Exception {
pub mod regs;
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct SegmentRegister {
pub base: u64,
pub limit: u32,
@@ -174,7 +173,6 @@ macro_rules! msr_data {
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct StandardRegisters {
pub rax: u64,
pub rbx: u64,
@@ -197,14 +195,12 @@ pub struct StandardRegisters {
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct DescriptorTable {
pub base: u64,
pub limit: u16,
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
pub struct SpecialRegisters {
pub cs: SegmentRegister,
pub ds: SegmentRegister,

View File

@@ -166,7 +166,7 @@ pub trait Hypervisor: Send + Sync {
CpuVendor::AMD
} else {
// Not known yet, the corresponding manufacturer manual should contain the
// necesssary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String
// necessary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String
CpuVendor::default()
}
}

View File

@@ -77,46 +77,61 @@ static VGIC_DIST_REGS: &[DistReg] = &[
VGIC_DIST_REG!(GICD_IPRIORITYR, 8, 0),
];
fn dist_attr_access(gic: &DeviceFd, offset: u32, val: &u32, set: bool) -> Result<()> {
fn dist_attr_set(gic: &DeviceFd, offset: u32, val: u32) -> Result<()> {
let gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
attr: offset as u64,
addr: &val as *const u32 as u64,
flags: 0,
};
gic.set_device_attr(&gic_dist_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
Ok(())
}
fn dist_attr_get(gic: &DeviceFd, offset: u32) -> Result<u32> {
let mut val = 0;
let mut gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
attr: offset as u64,
addr: val as *const u32 as u64,
addr: &mut val as *mut u32 as u64,
flags: 0,
};
if set {
gic.set_device_attr(&gic_dist_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else {
gic.get_device_attr(&mut gic_dist_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
}
Ok(())
// get_device_attr should be marked as unsafe, and will be in future.
// SAFETY: gic_dist_attr.addr is safe to write to.
gic.get_device_attr(&mut gic_dist_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
Ok(val)
}
/// Get the distributor control register.
pub fn read_ctlr(gic: &DeviceFd) -> Result<u32> {
let val: u32 = 0;
dist_attr_access(gic, GICD_CTLR, &val, false)?;
Ok(val)
dist_attr_get(gic, GICD_CTLR)
}
/// Set the distributor control register.
pub fn write_ctlr(gic: &DeviceFd, val: u32) -> Result<()> {
dist_attr_access(gic, GICD_CTLR, &val, true)
dist_attr_set(gic, GICD_CTLR, val)
}
fn get_interrupts_num(gic: &DeviceFd) -> Result<u32> {
let num_irq = 0;
let mut num_irq = 0;
let mut nr_irqs_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
attr: 0,
addr: &num_irq as *const u32 as u64,
addr: &mut num_irq as *mut u32 as u64,
flags: 0,
};
// get_device_attr should be marked as unsafe, and will be in future.
// SAFETY: nr_irqs_attr.addr is safe to write to.
gic.get_device_attr(&mut nr_irqs_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
@@ -158,8 +173,7 @@ pub fn set_dist_regs(gic: &DeviceFd, state: &[u32]) -> Result<()> {
let end = compute_reg_len(gic, dreg, base)?;
while base < end {
let val = state[idx];
dist_attr_access(gic, base, &val, true)?;
dist_attr_set(gic, base, state[idx])?;
idx += 1;
base += REG_SIZE as u32;
}
@@ -175,9 +189,7 @@ pub fn get_dist_regs(gic: &DeviceFd) -> Result<Vec<u32>> {
let end = compute_reg_len(gic, dreg, base)?;
while base < end {
let val: u32 = 0;
dist_attr_access(gic, base, &val, false)?;
state.push(val);
state.push(dist_attr_get(gic, base)?);
base += REG_SIZE as u32;
}
}

View File

@@ -79,23 +79,38 @@ static VGIC_ICC_REGS: &[u64] = &[
SYS_ICC_AP1R3_EL1,
];
fn icc_attr_access(gic: &DeviceFd, offset: u64, typer: u64, val: &u32, set: bool) -> Result<()> {
fn icc_attr_set(gic: &DeviceFd, offset: u64, typer: u64, val: u32) -> Result<()> {
let gic_icc_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
attr: ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | offset), // this needs the mpidr
addr: &val as *const u32 as u64,
flags: 0,
};
gic.set_device_attr(&gic_icc_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
Ok(())
}
fn icc_attr_get(gic: &DeviceFd, offset: u64, typer: u64) -> Result<u32> {
let mut val = 0;
let mut gic_icc_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
attr: ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | offset), // this needs the mpidr
addr: val as *const u32 as u64,
addr: &mut val as *mut u32 as u64,
flags: 0,
};
if set {
gic.set_device_attr(&gic_icc_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else {
gic.get_device_attr(&mut gic_icc_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
}
Ok(())
// get_device_attr should be marked as unsafe, and will be in future.
// SAFETY: gic_icc_attr.addr is safe to write to.
gic.get_device_attr(&mut gic_icc_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
Ok(val)
}
/// Get ICC registers.
@@ -107,10 +122,9 @@ pub fn get_icc_regs(gic: &DeviceFd, gicr_typer: &[u64]) -> Result<Vec<u32>> {
for ix in gicr_typer {
let i = *ix;
for icc_offset in VGIC_ICC_REGS {
let val = 0;
if *icc_offset == SYS_ICC_CTLR_EL1 {
// calculate priority bits by reading the ctrl_el1 register.
icc_attr_access(gic, *icc_offset, i, &val, false)?;
let val = icc_attr_get(gic, *icc_offset, i)?;
// The priority bits are found in the ICC_CTLR_EL1 register (bits from 10:8).
// See page 194 from https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_
// architecture_specification.pdf.
@@ -130,8 +144,7 @@ pub fn get_icc_regs(gic: &DeviceFd, gicr_typer: &[u64]) -> Result<Vec<u32>> {
// 7 bits of priority.
else if *icc_offset == SYS_ICC_AP0R1_EL1 || *icc_offset == SYS_ICC_AP1R1_EL1 {
if num_priority_bits >= 6 {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
state.push(icc_attr_get(gic, *icc_offset, i)?);
}
} else if *icc_offset == SYS_ICC_AP0R2_EL1
|| *icc_offset == SYS_ICC_AP0R3_EL1
@@ -139,12 +152,10 @@ pub fn get_icc_regs(gic: &DeviceFd, gicr_typer: &[u64]) -> Result<Vec<u32>> {
|| *icc_offset == SYS_ICC_AP1R3_EL1
{
if num_priority_bits == 7 {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
state.push(icc_attr_get(gic, *icc_offset, i)?);
}
} else {
icc_attr_access(gic, *icc_offset, i, &val, false)?;
state.push(val);
state.push(icc_attr_get(gic, *icc_offset, i)?);
}
}
}
@@ -165,7 +176,7 @@ pub fn set_icc_regs(gic: &DeviceFd, gicr_typer: &[u64], state: &[u32]) -> Result
}
if *icc_offset == SYS_ICC_AP0R1_EL1 || *icc_offset == SYS_ICC_AP1R1_EL1 {
if num_priority_bits >= 6 {
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
icc_attr_set(gic, *icc_offset, i, state[idx])?;
idx += 1;
}
continue;
@@ -176,12 +187,12 @@ pub fn set_icc_regs(gic: &DeviceFd, gicr_typer: &[u64], state: &[u32]) -> Result
|| *icc_offset == SYS_ICC_AP1R3_EL1
{
if num_priority_bits == 7 {
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
icc_attr_set(gic, *icc_offset, i, state[idx])?;
idx += 1;
}
continue;
}
icc_attr_access(gic, *icc_offset, i, &state[idx], true)?;
icc_attr_set(gic, *icc_offset, i, state[idx])?;
idx += 1;
}
}

View File

@@ -24,34 +24,38 @@ const GITS_CWRITER: u32 = 0x0088;
const GITS_CREADR: u32 = 0x0090;
const GITS_BASER: u32 = 0x0100;
/// Access an ITS device attribute.
///
/// This is a helper function to get/set the ITS device attribute depending
/// the bool parameter `set` provided.
pub fn gicv3_its_attr_access(
its_device: &DeviceFd,
group: u32,
attr: u32,
val: &u64,
set: bool,
) -> Result<()> {
fn gicv3_its_attr_set(its_device: &DeviceFd, group: u32, attr: u32, val: u64) -> Result<()> {
let gicv3_its_attr = kvm_bindings::kvm_device_attr {
group,
attr: attr as u64,
addr: &val as *const u64 as u64,
flags: 0,
};
its_device
.set_device_attr(&gicv3_its_attr)
.map_err(|e| Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into())))
}
fn gicv3_its_attr_get(its_device: &DeviceFd, group: u32, attr: u32) -> Result<u64> {
let mut val = 0;
let mut gicv3_its_attr = kvm_bindings::kvm_device_attr {
group,
attr: attr as u64,
addr: val as *const u64 as u64,
addr: &mut val as *mut u64 as u64,
flags: 0,
};
if set {
its_device.set_device_attr(&gicv3_its_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})
} else {
its_device
.get_device_attr(&mut gicv3_its_attr)
.map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})
}
// get_device_attr should be marked as unsafe, and will be in future.
// SAFETY: gicv3_its_attr.addr is safe to write to.
its_device
.get_device_attr(&mut gicv3_its_attr)
.map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
Ok(val)
}
/// Function that saves/restores ITS tables into guest RAM.
@@ -324,60 +328,43 @@ impl Vgic for KvmGicV3Its {
let icc_state = get_icc_regs(&self.device, &gicr_typers)?;
let its_baser_state: [u64; 8] = [0; 8];
let mut its_baser_state: [u64; 8] = [0; 8];
for i in 0..8 {
gicv3_its_attr_access(
its_baser_state[i as usize] = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8,
&its_baser_state[i as usize],
false,
)?;
}
let its_ctlr_state: u64 = 0;
gicv3_its_attr_access(
let its_ctlr_state = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR,
&its_ctlr_state,
false,
)?;
let its_cbaser_state: u64 = 0;
gicv3_its_attr_access(
let its_cbaser_state = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER,
&its_cbaser_state,
false,
)?;
let its_creadr_state: u64 = 0;
gicv3_its_attr_access(
let its_creadr_state = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR,
&its_creadr_state,
false,
)?;
let its_cwriter_state: u64 = 0;
gicv3_its_attr_access(
let its_cwriter_state = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER,
&its_cwriter_state,
false,
)?;
let its_iidr_state: u64 = 0;
gicv3_its_attr_access(
let its_iidr_state = gicv3_its_attr_get(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR,
&its_iidr_state,
false,
)?;
Ok(Gicv3ItsState {
@@ -407,57 +394,51 @@ impl Vgic for KvmGicV3Its {
set_icc_regs(&self.device, &gicr_typers, &state.icc)?;
//Restore GICv3ITS registers
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR,
&state.its_iidr,
true,
state.its_iidr,
)?;
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER,
&state.its_cbaser,
true,
state.its_cbaser,
)?;
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR,
&state.its_creadr,
true,
state.its_creadr,
)?;
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER,
&state.its_cwriter,
true,
state.its_cwriter,
)?;
for i in 0..8 {
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8,
&state.its_baser[i as usize],
true,
state.its_baser[i as usize],
)?;
}
// Restore ITS tables
gicv3_its_tables_access(self.its_device.as_ref().unwrap(), false)?;
gicv3_its_attr_access(
gicv3_its_attr_set(
self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR,
&state.its_ctlr,
true,
state.its_ctlr,
)
}

View File

@@ -46,7 +46,7 @@ const KVM_ARM64_SYSREG_MPIDR_EL1: u64 = KVM_REG_ARM64
| (((5_u64) << KVM_REG_ARM64_SYSREG_OP2_SHIFT) & KVM_REG_ARM64_SYSREG_OP2_MASK as u64);
/// This is how we represent the registers of a distributor.
/// It is relrvant their offset from the base address of the
/// It is relevant their offset from the base address of the
/// distributor.
/// Each register has a different number
/// of bits_per_irq and is therefore variable length.
@@ -96,23 +96,38 @@ static VGIC_SGI_REGS: &[RdistReg] = &[
VGIC_RDIST_REG!(GICR_IPRIORITYR0, 32),
];
fn redist_attr_access(gic: &DeviceFd, offset: u32, typer: u64, val: &u32, set: bool) -> Result<()> {
fn redist_attr_set(gic: &DeviceFd, offset: u32, typer: u64, val: u32) -> Result<()> {
let gic_redist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
attr: (typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (offset as u64), // this needs the mpidr
addr: &val as *const u32 as u64,
flags: 0,
};
gic.set_device_attr(&gic_redist_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
Ok(())
}
fn redist_attr_get(gic: &DeviceFd, offset: u32, typer: u64) -> Result<u32> {
let mut val = 0;
let mut gic_redist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
attr: (typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (offset as u64), // this needs the mpidr
addr: val as *const u32 as u64,
addr: &mut val as *mut u32 as u64,
flags: 0,
};
if set {
gic.set_device_attr(&gic_redist_attr).map_err(|e| {
Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else {
gic.get_device_attr(&mut gic_redist_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
}
Ok(())
// get_device_attr should be marked as unsafe, and will be in future.
// SAFETY: gic_redist_attr.addr is safe to write to.
gic.get_device_attr(&mut gic_redist_attr).map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
Ok(val)
}
fn access_redists_aux(
@@ -129,14 +144,11 @@ fn access_redists_aux(
let end = base + rdreg.length as u32;
while base < end {
let mut val = 0;
if set {
val = state[*idx];
redist_attr_access(gic, base, *i, &val, true)?;
redist_attr_set(gic, base, *i, state[*idx])?;
*idx += 1;
} else {
redist_attr_access(gic, base, *i, &val, false)?;
state.push(val);
state.push(redist_attr_get(gic, base, *i)?);
}
base += REG_SIZE as u32;
}

View File

@@ -106,12 +106,23 @@ pub fn is_system_register(regid: u64) -> bool {
}
pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
if !kvm.check_extension(Cap::SignalMsi) {
return Err(KvmError::CapabilityMissing(Cap::SignalMsi));
}
if !kvm.check_extension(Cap::OneReg) {
return Err(KvmError::CapabilityMissing(Cap::OneReg));
macro_rules! check_extension {
($cap:expr) => {
if !kvm.check_extension($cap) {
return Err(KvmError::CapabilityMissing($cap));
}
};
}
// SetGuestDebug is required but some kernels have it implemented without the capability flag.
check_extension!(Cap::ImmediateExit);
check_extension!(Cap::Ioeventfd);
check_extension!(Cap::Irqchip);
check_extension!(Cap::Irqfd);
check_extension!(Cap::IrqRouting);
check_extension!(Cap::MpState);
check_extension!(Cap::OneReg);
check_extension!(Cap::UserMemory);
Ok(())
}

View File

@@ -535,9 +535,9 @@ impl vm::Vm for KvmVm {
if self.check_extension(crate::kvm::Cap::MsiDevid) {
// On AArch64, there is limitation on the range of the 'devid',
// it can not be greater than 65536 (the max of u16).
// it cannot be greater than 65536 (the max of u16).
//
// BDF can not be used directly, because 'segment' is in high
// BDF cannot be used directly, because 'segment' is in high
// 16 bits. The layout of the u32 BDF is:
// |---- 16 bits ----|-- 8 bits --|-- 5 bits --|-- 3 bits --|
// | segment | bus | device | function |
@@ -1505,7 +1505,7 @@ impl cpu::Vcpu for KvmVcpu {
#[cfg(target_arch = "x86_64")]
///
/// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct.
/// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioctl.
///
fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> {
let fpu: kvm_bindings::kvm_fpu = (*fpu).clone().into();
@@ -1986,7 +1986,7 @@ impl cpu::Vcpu for KvmVcpu {
/// SREGS saves/restores a pending interrupt, similar to what
/// VCPU_EVENTS also does.
///
/// GET_MSRS requires a pre-populated data structure to do something
/// GET_MSRS requires a prepopulated data structure to do something
/// meaningful. For SET_MSRS it will then contain good data.
///
/// # Example

View File

@@ -32,29 +32,37 @@ pub use {
/// Check KVM extension for Linux
///
pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
if !kvm.check_extension(Cap::SignalMsi) {
return Err(KvmError::CapabilityMissing(Cap::SignalMsi));
}
if !kvm.check_extension(Cap::TscDeadlineTimer) {
return Err(KvmError::CapabilityMissing(Cap::TscDeadlineTimer));
}
if !kvm.check_extension(Cap::SplitIrqchip) {
return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip));
}
if !kvm.check_extension(Cap::SetIdentityMapAddr) {
return Err(KvmError::CapabilityMissing(Cap::SetIdentityMapAddr));
}
if !kvm.check_extension(Cap::SetTssAddr) {
return Err(KvmError::CapabilityMissing(Cap::SetTssAddr));
}
if !kvm.check_extension(Cap::ImmediateExit) {
return Err(KvmError::CapabilityMissing(Cap::ImmediateExit));
}
if !kvm.check_extension(Cap::GetTscKhz) {
return Err(KvmError::CapabilityMissing(Cap::GetTscKhz));
macro_rules! check_extension {
($cap:expr) => {
if !kvm.check_extension($cap) {
return Err(KvmError::CapabilityMissing($cap));
}
};
}
// DeviceCtrl, EnableCap, and SetGuestDebug are also required, but some kernels have
// the features implemented without the capability flags.
check_extension!(Cap::AdjustClock);
check_extension!(Cap::ExtCpuid);
check_extension!(Cap::GetTscKhz);
check_extension!(Cap::ImmediateExit);
check_extension!(Cap::Ioeventfd);
check_extension!(Cap::Irqchip);
check_extension!(Cap::Irqfd);
check_extension!(Cap::IrqRouting);
check_extension!(Cap::MpState);
check_extension!(Cap::SetIdentityMapAddr);
check_extension!(Cap::SetTssAddr);
check_extension!(Cap::SplitIrqchip);
check_extension!(Cap::TscDeadlineTimer);
check_extension!(Cap::UserMemory);
check_extension!(Cap::UserNmi);
check_extension!(Cap::VcpuEvents);
check_extension!(Cap::Xcrs);
check_extension!(Cap::Xsave);
Ok(())
}
#[derive(Clone, Serialize, Deserialize)]
pub struct VcpuKvmState {
pub cpuid: Vec<CpuIdEntry>,

View File

@@ -165,7 +165,7 @@ pub enum ClockData {
#[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_clock_data),
#[cfg(feature = "mshv")]
Mshv, /* MSHV does not support ClockData yet */
Mshv(mshv::MshvClockData),
}
#[cfg(target_arch = "x86_64")]

View File

@@ -3,13 +3,12 @@
// Copyright © 2020, Microsoft Corporation
//
use crate::arch::emulator::{PlatformEmulator, PlatformError};
use crate::arch::emulator::PlatformEmulator;
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::emulator::{Emulator, EmulatorCpuState};
use crate::arch::x86::emulator::Emulator;
use crate::cpu;
use crate::cpu::Vcpu;
use crate::hypervisor;
use crate::mshv::emulator::MshvEmulatorContext;
use crate::vec_with_array_field;
use crate::vm::{self, InterruptSourceConfig, VmOps};
use crate::HypervisorType;
@@ -20,18 +19,15 @@ use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use vfio_ioctls::VfioDeviceFd;
use vm::DataMatch;
#[cfg(feature = "sev_snp")]
mod snp_constants;
// x86_64 dependencies
#[cfg(target_arch = "x86_64")]
pub mod x86_64;
#[cfg(feature = "sev_snp")]
use snp_constants::*;
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{CpuIdEntry, FpuState, MsrEntry};
#[cfg(target_arch = "x86_64")]
use crate::ClockData;
use crate::{
CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion,
USER_MEMORY_REGION_ADJUSTABLE, USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ,
@@ -39,18 +35,16 @@ use crate::{
};
#[cfg(feature = "sev_snp")]
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
use vmm_sys_util::eventfd::EventFd;
#[cfg(target_arch = "x86_64")]
pub use x86_64::VcpuMshvState;
#[cfg(target_arch = "x86_64")]
pub use x86_64::*;
#[cfg(feature = "sev_snp")]
use snp_constants::*;
#[cfg(target_arch = "x86_64")]
use std::fs::File;
use std::os::unix::io::AsRawFd;
use vmm_sys_util::eventfd::EventFd;
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{CpuIdEntry, FpuState, MsrEntry};
pub use x86_64::*;
#[cfg(target_arch = "x86_64")]
pub use x86_64::{emulator, VcpuMshvState};
const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4;
const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8;
@@ -60,7 +54,7 @@ const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8;
///
pub use {
mshv_bindings::mshv_create_device as CreateDevice,
mshv_bindings::mshv_device_attr as DeviceAttr, mshv_ioctls::DeviceFd,
mshv_bindings::mshv_device_attr as DeviceAttr, mshv_ioctls, mshv_ioctls::DeviceFd,
};
pub const PAGE_SHIFT: usize = 12;
@@ -92,6 +86,25 @@ impl From<mshv_user_mem_region> for UserMemoryRegion {
}
}
#[cfg(target_arch = "x86_64")]
impl From<MshvClockData> for ClockData {
fn from(d: MshvClockData) -> Self {
ClockData::Mshv(d)
}
}
#[cfg(target_arch = "x86_64")]
impl From<ClockData> for MshvClockData {
fn from(ms: ClockData) -> Self {
match ms {
ClockData::Mshv(s) => s,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => unreachable!("MSHV clock data is not valid"),
}
}
}
impl From<UserMemoryRegion> for mshv_user_mem_region {
fn from(region: UserMemoryRegion) -> Self {
let mut flags: u32 = 0;
@@ -254,6 +267,7 @@ impl hypervisor::Hypervisor for MshvHypervisor {
}
// Set additional partition property for SEV-SNP partition.
#[cfg(target_arch = "x86_64")]
if mshv_vm_type == VmType::Snp {
let snp_policy = snp::get_default_snp_guest_policy();
let vmgexit_offloads = snp::get_default_vmgexit_offload_features();
@@ -285,12 +299,20 @@ impl hypervisor::Hypervisor for MshvHypervisor {
// to override this behavior with a more suitable option i.e., ignore
// writes from the guest and return zero in attempt to read unimplemented
// MSR.
#[cfg(target_arch = "x86_64")]
fd.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_UNIMPLEMENTED_MSR_ACTION,
hv_unimplemented_msr_action_HV_UNIMPLEMENTED_MSR_ACTION_IGNORE_WRITE_READ_ZERO as u64,
)
.map_err(|e| hypervisor::HypervisorError::SetPartitionProperty(e.into()))?;
// Always create a frozen partition
fd.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
1u64,
)
.map_err(|e| hypervisor::HypervisorError::SetPartitionProperty(e.into()))?;
let vm_fd = Arc::new(fd);
#[cfg(target_arch = "x86_64")]
@@ -346,7 +368,16 @@ impl hypervisor::Hypervisor for MshvHypervisor {
/// Get the supported CpuID
///
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
Ok(Vec::new())
let mut cpuid = Vec::new();
let functions: [u32; 2] = [0x1, 0xb];
for function in functions {
cpuid.push(CpuIdEntry {
function,
..Default::default()
});
}
Ok(cpuid)
}
/// Get maximum number of vCPUs
@@ -600,14 +631,18 @@ impl cpu::Vcpu for MshvVcpu {
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
hv_message_type_HVMSG_UNMAPPED_GPA => {
msg_type @ (hv_message_type_HVMSG_UNMAPPED_GPA
| hv_message_type_HVMSG_GPA_INTERCEPT) => {
let info = x.to_memory_info().unwrap();
let insn_len = info.instruction_byte_count as usize;
assert!(insn_len > 0 && insn_len <= 16);
let gva = info.guest_virtual_address;
let gpa = info.guest_physical_address;
debug!("Exit ({:?}) GVA {:x} GPA {:x}", msg_type, gva, gpa);
let mut context = MshvEmulatorContext {
vcpu: self,
map: (info.guest_virtual_address, info.guest_physical_address),
map: (gva, gpa),
};
// Create a new emulator.
@@ -615,7 +650,10 @@ impl cpu::Vcpu for MshvVcpu {
// Emulate the trapped instruction, and only the first one.
let new_state = emul
.emulate_first_insn(self.vp_index as usize, &info.instruction_bytes)
.emulate_first_insn(
self.vp_index as usize,
&info.instruction_bytes[..insn_len],
)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
// Set CPU state back.
@@ -678,6 +716,7 @@ impl cpu::Vcpu for MshvVcpu {
)))?;
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
hv_message_type_HVMSG_UNACCEPTED_GPA => {
let info = x.to_memory_info().unwrap();
let gva = info.guest_virtual_address;
@@ -689,11 +728,13 @@ impl cpu::Vcpu for MshvVcpu {
gva,
)))
}
#[cfg(target_arch = "x86_64")]
hv_message_type_HVMSG_X64_CPUID_INTERCEPT => {
let info = x.to_cpuid_info().unwrap();
debug!("cpuid eax: {:x}", { info.rax });
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
hv_message_type_HVMSG_X64_MSR_INTERCEPT => {
let info = x.to_msr_info().unwrap();
if info.header.intercept_access_type == 0 {
@@ -703,6 +744,7 @@ impl cpu::Vcpu for MshvVcpu {
}
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
hv_message_type_HVMSG_X64_EXCEPTION_INTERCEPT => {
//TODO: Handler for VMCALL here.
let info = x.to_exception_info().unwrap();
@@ -757,6 +799,10 @@ impl cpu::Vcpu for MshvVcpu {
}
GHCB_INFO_REGISTER_REQUEST => {
let mut ghcb_gpa = hv_x64_register_sev_ghcb::default();
// Disable the previously used GHCB page.
self.disable_prev_ghcb_page()?;
// SAFETY: Accessing a union element from bindgen generated bindings.
unsafe {
ghcb_gpa.__bindgen_anon_1.set_enabled(1);
@@ -784,6 +830,7 @@ impl cpu::Vcpu for MshvVcpu {
resp_ghcb_msr.__bindgen_anon_2.set_gpa_page_number(
ghcb_msr.__bindgen_anon_2.gpa_page_number(),
);
debug!("GHCB GPA is {:x}", ghcb_gpa.as_uint64);
}
// SAFETY: Accessing a union element from bindgen generated bindings.
let reg_name_value = unsafe {
@@ -884,15 +931,7 @@ impl cpu::Vcpu for MshvVcpu {
)?;
// Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg =
mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd.gpa_write(&mut swei1_rw_gpa_arg).map_err(
|e| cpu::HypervisorCpuError::GpaWrite(e.into()),
)?;
self.clear_swexit_info1(ghcb_gpa)?;
}
SVM_NAE_HV_DOORBELL_PAGE_QUERY => {
let mut reg_assocs = [ hv_register_assoc {
@@ -914,6 +953,9 @@ impl cpu::Vcpu for MshvVcpu {
self.fd.gpa_write(&mut swei2_rw_gpa_arg).map_err(
|e| cpu::HypervisorCpuError::GpaWrite(e.into()),
)?;
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
}
SVM_NAE_HV_DOORBELL_PAGE_CLEAR => {
let mut swei2_rw_gpa_arg =
@@ -1014,14 +1056,7 @@ impl cpu::Vcpu for MshvVcpu {
}
// Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
self.clear_swexit_info1(ghcb_gpa)?;
}
SVM_EXITCODE_MMIO_READ => {
let src_gpa =
@@ -1050,6 +1085,9 @@ impl cpu::Vcpu for MshvVcpu {
self.fd
.gpa_write(&mut arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
}
SVM_EXITCODE_MMIO_WRITE => {
let dst_gpa =
@@ -1078,6 +1116,9 @@ impl cpu::Vcpu for MshvVcpu {
cpu::HypervisorCpuError::RunVcpu(e.into())
})?;
}
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
}
SVM_EXITCODE_SNP_GUEST_REQUEST => {
let req_gpa =
@@ -1123,15 +1164,8 @@ impl cpu::Vcpu for MshvVcpu {
.sev_snp_ap_create(&mshv_ap_create_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
// Clear the SW_EXIT_INFO1 register to indicate no error
self.clear_swexit_info1(ghcb_gpa)?;
}
_ => panic!(
"GHCB_INFO_NORMAL: Unhandled exit code: {:0x}",
@@ -1288,7 +1322,7 @@ impl cpu::Vcpu for MshvVcpu {
self.set_fpu(&state.fpu)?;
self.set_xcrs(&state.xcrs)?;
// These registers are global and needed to be set only for first VCPU
// as Microsoft Hypervisor allows setting this regsier for only one VCPU
// as Microsoft Hypervisor allows setting this register for only one VCPU
if self.vp_index == 0 {
self.fd
.set_misc_regs(&state.misc)
@@ -1427,6 +1461,42 @@ impl cpu::Vcpu for MshvVcpu {
}
impl MshvVcpu {
///
/// Deactivate previously used GHCB page.
///
#[cfg(feature = "sev_snp")]
fn disable_prev_ghcb_page(&self) -> cpu::Result<()> {
let mut reg_assocs = [hv_register_assoc {
name: hv_register_name_HV_X64_REGISTER_SEV_GHCB_GPA,
..Default::default()
}];
self.fd.get_reg(&mut reg_assocs).unwrap();
// SAFETY: Accessing a union element from bindgen generated bindings.
let prev_ghcb_gpa = unsafe { reg_assocs[0].value.reg64 };
debug!("Prev GHCB GPA is {:x}", prev_ghcb_gpa);
let mut ghcb_gpa = hv_x64_register_sev_ghcb::default();
// SAFETY: Accessing a union element from bindgen generated bindings.
unsafe {
ghcb_gpa.__bindgen_anon_1.set_enabled(0);
ghcb_gpa.__bindgen_anon_1.set_page_number(prev_ghcb_gpa);
}
// SAFETY: Accessing a union element from bindgen generated bindings.
let reg_name_value = unsafe {
[(
hv_register_name_HV_X64_REGISTER_SEV_GHCB_GPA,
ghcb_gpa.as_uint64,
)]
};
set_registers_64!(self.fd, reg_name_value)
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
Ok(())
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that returns the vcpu's current "xcrs".
@@ -1468,133 +1538,26 @@ impl MshvVcpu {
.set_vcpu_events(events)
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
}
}
#[cfg(target_arch = "x86_64")]
struct MshvEmulatorContext<'a> {
vcpu: &'a MshvVcpu,
map: (u64, u64), // Initial GVA to GPA mapping provided by the hypervisor
}
///
/// Clear SW_EXIT_INFO1 register for SEV-SNP guests.
///
#[cfg(feature = "sev_snp")]
fn clear_swexit_info1(
&self,
ghcb_gpa: u64,
) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
// Clear the SW_EXIT_INFO1 register to indicate no error
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei1_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
#[cfg(target_arch = "x86_64")]
impl<'a> MshvEmulatorContext<'a> {
// Do the actual gva -> gpa translation
#[allow(non_upper_case_globals)]
fn translate(&self, gva: u64) -> Result<u64, PlatformError> {
if self.map.0 == gva {
return Ok(self.map.1);
}
// TODO: More fine-grained control for the flags
let flags = HV_TRANSLATE_GVA_VALIDATE_READ | HV_TRANSLATE_GVA_VALIDATE_WRITE;
let (gpa, result_code) = self
.vcpu
.translate_gva(gva, flags.into())
.map_err(|e| PlatformError::TranslateVirtualAddress(anyhow!(e)))?;
match result_code {
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => Ok(gpa),
_ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))),
}
}
}
#[cfg(target_arch = "x86_64")]
/// Platform emulation for Hyper-V
impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
type CpuState = EmulatorCpuState;
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
let gpa = self.translate(gva)?;
debug!(
"mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]",
data.len(),
gva,
gpa
);
if let Some(vm_ops) = &self.vcpu.vm_ops {
if vm_ops.guest_mem_read(gpa, data).is_err() {
vm_ops
.mmio_read(gpa, data)
.map_err(|e| PlatformError::MemoryReadFailure(e.into()))?;
}
}
Ok(())
}
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
let gpa = self.translate(gva)?;
debug!(
"mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]",
data.len(),
gva,
gpa
);
if let Some(vm_ops) = &self.vcpu.vm_ops {
if vm_ops.guest_mem_write(gpa, data).is_err() {
vm_ops
.mmio_write(gpa, data)
.map_err(|e| PlatformError::MemoryWriteFailure(e.into()))?;
}
}
Ok(())
}
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError> {
if cpu_id != self.vcpu.vp_index as usize {
return Err(PlatformError::GetCpuStateFailure(anyhow!(
"CPU id mismatch {:?} {:?}",
cpu_id,
self.vcpu.vp_index
)));
}
let regs = self
.vcpu
.get_regs()
.map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?;
let sregs = self
.vcpu
.get_sregs()
.map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?;
debug!("mshv emulator: Getting new CPU state");
debug!("mshv emulator: {:#x?}", regs);
Ok(EmulatorCpuState { regs, sregs })
}
fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError> {
if cpu_id != self.vcpu.vp_index as usize {
return Err(PlatformError::SetCpuStateFailure(anyhow!(
"CPU id mismatch {:?} {:?}",
cpu_id,
self.vcpu.vp_index
)));
}
debug!("mshv emulator: Setting new CPU state");
debug!("mshv emulator: {:#x?}", state.regs);
self.vcpu
.set_regs(&state.regs)
.map_err(|e| PlatformError::SetCpuStateFailure(e.into()))?;
self.vcpu
.set_sregs(&state.sregs)
.map_err(|e| PlatformError::SetCpuStateFailure(e.into()))
}
fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError> {
self.translate(gva)
}
fn fetch(&self, _ip: u64, _instruction_bytes: &mut [u8]) -> Result<(), PlatformError> {
Err(PlatformError::MemoryReadFailure(anyhow!("unimplemented")))
Ok(cpu::VmExit::Ignore)
}
}
@@ -1930,13 +1893,23 @@ impl vm::Vm for MshvVm {
/// Retrieve guest clock.
#[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> {
Ok(ClockData::Mshv)
let val = self
.fd
.get_partition_property(hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME)
.map_err(|e| vm::HypervisorVmError::GetClock(e.into()))?;
Ok(MshvClockData { ref_time: val }.into())
}
/// Set guest clock.
#[cfg(target_arch = "x86_64")]
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
Ok(())
fn set_clock(&self, data: &ClockData) -> vm::Result<()> {
let data: MshvClockData = (*data).into();
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME,
data.ref_time,
)
.map_err(|e| vm::HypervisorVmError::SetClock(e.into()))
}
/// Downcast to the underlying MshvVm type
@@ -2047,4 +2020,70 @@ impl vm::Vm for MshvVm {
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
unimplemented!()
}
/// Pause the VM
fn pause(&self) -> vm::Result<()> {
// Freeze the partition
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
1u64,
)
.map_err(|e| {
vm::HypervisorVmError::SetVmProperty(anyhow!(
"Failed to set partition property: {}",
e
))
})
}
/// Resume the VM
fn resume(&self) -> vm::Result<()> {
// Resuming the partition using TIME_FREEZE property
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
0u64,
)
.map_err(|e| {
vm::HypervisorVmError::SetVmProperty(anyhow!(
"Failed to set partition property: {}",
e
))
})
}
#[cfg(feature = "sev_snp")]
fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> {
if !self.sev_snp_enabled {
return Ok(());
}
let start_gpfn: u64 = gpa >> PAGE_SHIFT;
let end_gpfn: u64 = (gpa + size as u64 - 1) >> PAGE_SHIFT;
let gpas: Vec<u64> = (start_gpfn..=end_gpfn).map(|x| x << PAGE_SHIFT).collect();
if !gpas.is_empty() {
let mut gpa_list = vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len());
gpa_list[0].gpa_list_size = gpas.len() as u64;
gpa_list[0].host_access = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE;
gpa_list[0].acquire = 1;
gpa_list[0].flags = 0;
// SAFETY: gpa_list initialized with gpas.len() and now it is being turned into
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
// everything from gpas.
unsafe {
let gpas_slice: &mut [u64] = gpa_list[0].gpa_list.as_mut_slice(gpas.len());
gpas_slice.copy_from_slice(gpas.as_slice());
}
self.fd
.modify_gpa_host_access(&gpa_list[0])
.map_err(|e| vm::HypervisorVmError::ModifyGpaHostAccess(e.into()))?;
}
Ok(())
}
}

View File

@@ -0,0 +1,145 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2024, Microsoft Corporation
//
use crate::arch::emulator::{PlatformEmulator, PlatformError};
use crate::arch::x86::emulator::{CpuStateManager, EmulatorCpuState};
use crate::cpu::Vcpu;
use crate::mshv::MshvVcpu;
use iced_x86::Register;
use mshv_bindings::*;
pub struct MshvEmulatorContext<'a> {
pub vcpu: &'a MshvVcpu,
pub map: (u64, u64), // Initial GVA to GPA mapping provided by the hypervisor
}
impl<'a> MshvEmulatorContext<'a> {
// Do the actual gva -> gpa translation
#[allow(non_upper_case_globals)]
fn translate(&self, gva: u64, flags: u32) -> Result<u64, PlatformError> {
if self.map.0 == gva {
return Ok(self.map.1);
}
let (gpa, result_code) = self
.vcpu
.translate_gva(gva, flags.into())
.map_err(|e| PlatformError::TranslateVirtualAddress(anyhow!(e)))?;
match result_code {
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => Ok(gpa),
_ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))),
}
}
fn read_memory_flags(
&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}]",
data.len(),
gva,
gpa
);
if let Some(vm_ops) = &self.vcpu.vm_ops {
if vm_ops.guest_mem_read(gpa, data).is_err() {
vm_ops
.mmio_read(gpa, data)
.map_err(|e| PlatformError::MemoryReadFailure(e.into()))?;
}
}
Ok(())
}
}
/// Platform emulation for Hyper-V
impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
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 gpa = self.translate(gva, HV_TRANSLATE_GVA_VALIDATE_WRITE)?;
debug!(
"mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]",
data.len(),
gva,
gpa
);
if let Some(vm_ops) = &self.vcpu.vm_ops {
if vm_ops.guest_mem_write(gpa, data).is_err() {
vm_ops
.mmio_write(gpa, data)
.map_err(|e| PlatformError::MemoryWriteFailure(e.into()))?;
}
}
Ok(())
}
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError> {
if cpu_id != self.vcpu.vp_index as usize {
return Err(PlatformError::GetCpuStateFailure(anyhow!(
"CPU id mismatch {:?} {:?}",
cpu_id,
self.vcpu.vp_index
)));
}
let regs = self
.vcpu
.get_regs()
.map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?;
let sregs = self
.vcpu
.get_sregs()
.map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?;
debug!("mshv emulator: Getting new CPU state");
debug!("mshv emulator: {:#x?}", regs);
Ok(EmulatorCpuState { regs, sregs })
}
fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError> {
if cpu_id != self.vcpu.vp_index as usize {
return Err(PlatformError::SetCpuStateFailure(anyhow!(
"CPU id mismatch {:?} {:?}",
cpu_id,
self.vcpu.vp_index
)));
}
debug!("mshv emulator: Setting new CPU state");
debug!("mshv emulator: {:#x?}", state.regs);
self.vcpu
.set_regs(&state.regs)
.map_err(|e| PlatformError::SetCpuStateFailure(e.into()))?;
self.vcpu
.set_sregs(&state.sregs)
.map_err(|e| PlatformError::SetCpuStateFailure(e.into()))
}
fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError> {
let rip =
self.cpu_state(self.vcpu.vp_index as usize)?
.linearize(Register::CS, ip, false)?;
self.read_memory_flags(
rip,
instruction_bytes,
HV_TRANSLATE_GVA_VALIDATE_READ | HV_TRANSLATE_GVA_VALIDATE_EXECUTE,
)
}
}

View File

@@ -14,6 +14,8 @@ use crate::arch::x86::{
use serde::{Deserialize, Serialize};
use std::fmt;
pub mod emulator;
///
/// Export generically-named wrappers of mshv_bindings for Unix-based platforms
///
@@ -43,6 +45,11 @@ pub struct VcpuMshvState {
pub vp_states: AllVpStateComponents,
}
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
pub struct MshvClockData {
pub ref_time: u64,
}
impl fmt::Display for VcpuMshvState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let expected_num_msrs = self.msrs.len();

View File

@@ -190,7 +190,7 @@ pub enum HypervisorVmError {
/// Assert virtual interrupt error
///
#[error("Failed to assert virtual Interrupt: {0}")]
AsserttVirtualInterrupt(#[source] anyhow::Error),
AssertVirtualInterrupt(#[source] anyhow::Error),
#[cfg(feature = "sev_snp")]
///
@@ -231,6 +231,16 @@ pub enum HypervisorVmError {
///
#[error("Failed to complete isolated import: {0}")]
CompleteIsolatedImport(#[source] anyhow::Error),
/// Failed to set VM property
///
#[error("Failed to set VM property: {0}")]
SetVmProperty(#[source] anyhow::Error),
///
/// Modify GPA host access error
///
#[cfg(feature = "sev_snp")]
#[error("Failed to modify GPA host access: {0}")]
ModifyGpaHostAccess(#[source] anyhow::Error),
}
///
/// Result type for returning from a function
@@ -390,6 +400,21 @@ pub trait Vm: Send + Sync + Any {
) -> Result<()> {
unimplemented!()
}
/// Pause the VM
fn pause(&self) -> Result<()> {
Ok(())
}
/// Resume the VM
fn resume(&self) -> Result<()> {
Ok(())
}
#[cfg(feature = "sev_snp")]
fn gain_page_access(&self, _gpa: u64, _size: u32) -> Result<()> {
Ok(())
}
}
pub trait VmOps: Send + Sync {

View File

@@ -1,8 +1,8 @@
[package]
name = "net_gen"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2021"
name = "net_gen"
version = "0.1.0"
[dependencies]
vmm-sys-util = "0.12.1"

View File

@@ -1,26 +1,30 @@
[package]
name = "net_util"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2021"
name = "net_util"
version = "0.1.0"
[dependencies]
epoll = "4.3.3"
getrandom = "0.2.13"
libc = "0.2.153"
log = "0.4.21"
getrandom = "0.2.14"
libc = "0.2.155"
log = "0.4.22"
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = "1.0.197"
thiserror = "1.0.58"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.62"
virtio-bindings = "0.2.2"
virtio-queue = "0.11.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
virtio-queue = "0.12.0"
vm-memory = { version = "0.14.1", features = [
"backend-atomic",
"backend-bitmap",
"backend-mmap",
] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1"
[dev-dependencies]
once_cell = "1.19.0"
pnet = "0.34.0"
pnet_datalink = "0.34.0"
serde_json = "1.0.115"
pnet = "0.35.0"
pnet_datalink = "0.35.0"
serde_json = "1.0.120"

8
net_util/build.rs Normal file
View File

@@ -0,0 +1,8 @@
// Copyright © 2024 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
fn main() {
println!("cargo::rustc-check-cfg=cfg(fuzzing)");
}

View File

@@ -67,7 +67,7 @@ fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
sin_family: net_gen::AF_INET as u16,
sin_port: 0,
// SAFETY: ip_addr can be safely transmute to in_addr
sin_addr: unsafe { mem::transmute(ip_addr.octets()) },
sin_addr: unsafe { mem::transmute::<[u8; 4], net_gen::inn::in_addr>(ip_addr.octets()) },
__pad: [0; 8usize],
};

View File

@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use super::{register_listener, unregister_listener, vnet_hdr_len, Tap};
use crate::GuestMemoryMmap;
use rate_limiter::{RateLimiter, TokenType};
use std::io;
use std::num::Wrapping;
@@ -12,6 +11,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use thiserror::Error;
use virtio_queue::{Queue, QueueOwnedT, QueueT};
use vm_memory::bitmap::Bitmap;
use vm_memory::{Bytes, GuestMemory};
use vm_virtio::{AccessPlatform, Translatable};
@@ -19,6 +19,7 @@ use vm_virtio::{AccessPlatform, Translatable};
pub struct TxVirtio {
pub counter_bytes: Wrapping<u64>,
pub counter_frames: Wrapping<u64>,
iovecs: IovecBuffer,
}
impl Default for TxVirtio {
@@ -32,12 +33,13 @@ impl TxVirtio {
TxVirtio {
counter_bytes: Wrapping(0),
counter_frames: Wrapping(0),
iovecs: IovecBuffer::new(),
}
}
pub fn process_desc_chain(
pub fn process_desc_chain<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
tap: &Tap,
queue: &mut Queue,
rate_limiter: &mut Option<RateLimiter>,
@@ -54,7 +56,7 @@ impl TxVirtio {
let mut next_desc = desc_chain.next();
let mut iovecs = Vec::new();
let mut iovecs = self.iovecs.borrow();
while let Some(desc) = next_desc {
let desc_addr = desc
.addr()
@@ -145,6 +147,7 @@ impl TxVirtio {
pub struct RxVirtio {
pub counter_bytes: Wrapping<u64>,
pub counter_frames: Wrapping<u64>,
iovecs: IovecBuffer,
}
impl Default for RxVirtio {
@@ -158,12 +161,13 @@ impl RxVirtio {
RxVirtio {
counter_bytes: Wrapping(0),
counter_frames: Wrapping(0),
iovecs: IovecBuffer::new(),
}
}
pub fn process_desc_chain(
pub fn process_desc_chain<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
tap: &Tap,
queue: &mut Queue,
rate_limiter: &mut Option<RateLimiter>,
@@ -193,7 +197,7 @@ impl RxVirtio {
.ok_or(NetQueuePairError::DescriptorInvalidHeader)?;
let mut next_desc = Some(desc);
let mut iovecs = Vec::new();
let mut iovecs = self.iovecs.borrow();
while let Some(desc) = next_desc {
let desc_addr = desc
.addr()
@@ -288,6 +292,53 @@ impl RxVirtio {
}
}
#[derive(Default, Clone)]
struct IovecBuffer(Vec<libc::iovec>);
// SAFETY: Implementing Send for IovecBuffer is safe as the pointer inside is iovec.
// The iovecs are usually constructed from virtio descriptors, which are safe to send across
// threads.
unsafe impl Send for IovecBuffer {}
// SAFETY: Implementing Sync for IovecBuffer is safe as the pointer inside is iovec.
// The iovecs are usually constructed from virtio descriptors, which are safe to access from
// multiple threads.
unsafe impl Sync for IovecBuffer {}
impl IovecBuffer {
fn new() -> Self {
// Here we use 4 as the default capacity because it is enough for most cases.
const DEFAULT_CAPACITY: usize = 4;
IovecBuffer(Vec::with_capacity(DEFAULT_CAPACITY))
}
fn borrow(&mut self) -> IovecBufferBorrowed<'_> {
IovecBufferBorrowed(&mut self.0)
}
}
struct IovecBufferBorrowed<'a>(&'a mut Vec<libc::iovec>);
impl<'a> std::ops::Deref for IovecBufferBorrowed<'a> {
type Target = Vec<libc::iovec>;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<'a> std::ops::DerefMut for IovecBufferBorrowed<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl Drop for IovecBufferBorrowed<'_> {
fn drop(&mut self) {
// Clear the buffer to make sure old values are not used after
self.0.clear();
}
}
#[derive(Default, Clone)]
pub struct NetCounters {
pub tx_bytes: Arc<AtomicU64>,
@@ -350,9 +401,9 @@ pub struct NetQueuePair {
}
impl NetQueuePair {
pub fn process_tx(
pub fn process_tx<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
queue: &mut Queue,
) -> Result<bool, NetQueuePairError> {
let tx_tap_retry = self.tx.process_desc_chain(
@@ -400,9 +451,9 @@ impl NetQueuePair {
.map_err(NetQueuePairError::QueueNeedsNotification)
}
pub fn process_rx(
pub fn process_rx<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
queue: &mut Queue,
) -> Result<bool, NetQueuePairError> {
self.rx_desc_avail = !self.rx.process_desc_chain(
@@ -418,7 +469,7 @@ impl NetQueuePair {
.map_or(false, |r| r.is_blocked());
// Stop listening on the `RX_TAP_EVENT` when:
// 1) there is no available describles, or
// 1) there is no available describes, or
// 2) the RX rate limit is reached.
if self.rx_tap_listening && (!self.rx_desc_avail || rate_limit_reached) {
unregister_listener(

View File

@@ -1,5 +1,5 @@
[package]
name = "option_parser"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
name = "option_parser"
version = "0.1.0"

View File

@@ -23,6 +23,7 @@ pub enum OptionParserError {
UnknownOption(String),
InvalidSyntax(String),
Conversion(String, String),
InvalidValue(String),
}
impl fmt::Display for OptionParserError {
@@ -33,6 +34,7 @@ impl fmt::Display for OptionParserError {
OptionParserError::Conversion(field, value) => {
write!(f, "unable to convert {value} for {field}")
}
OptionParserError::InvalidValue(s) => write!(f, "invalid value: {s}"),
}
}
}
@@ -203,7 +205,7 @@ impl FromStr for ByteSized {
0
};
let s = s.trim_end_matches(|c| c == 'K' || c == 'M' || c == 'G');
let s = s.trim_end_matches(['K', 'M', 'G']);
s.parse::<u64>()
.map_err(|_| ByteSizedParseError::InvalidValue(s.to_owned()))?
<< shift

View File

@@ -1,8 +1,8 @@
[package]
name = "pci"
version = "0.1.0"
authors = ["Samuel Ortiz <sameo@linux.intel.com>"]
edition = "2021"
name = "pci"
version = "0.1.0"
[features]
default = []
@@ -10,19 +10,24 @@ kvm = ["vfio-ioctls/kvm"]
mshv = ["vfio-ioctls/mshv"]
[dependencies]
anyhow = "1.0.81"
anyhow = "1.0.86"
byteorder = "1.5.0"
hypervisor = { path = "../hypervisor" }
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
libc = "0.2.155"
log = "0.4.22"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.62"
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = [
"fam-wrappers",
] }
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" }
vmm-sys-util = "0.12.1"
libc = "0.2.153"
log = "0.4.21"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.58"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-memory = { version = "0.14.1", features = [
"backend-atomic",
"backend-bitmap",
"backend-mmap",
] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = "0.12.1"

View File

@@ -14,7 +14,7 @@ use std::any::Any;
use std::collections::HashMap;
use std::ops::DerefMut;
use std::sync::{Arc, Barrier, Mutex};
use vm_device::{Bus, BusDevice};
use vm_device::{Bus, BusDevice, BusDeviceSync};
const VENDOR_ID_INTEL: u16 = 0x8086;
const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57;
@@ -122,7 +122,7 @@ impl PciBus {
pub fn register_mapping(
&self,
dev: Arc<Mutex<dyn BusDevice>>,
dev: Arc<dyn BusDeviceSync>,
#[cfg(target_arch = "x86_64")] io_bus: &Bus,
mmio_bus: &Bus,
bars: Vec<PciBarConfiguration>,
@@ -409,7 +409,7 @@ impl BusDevice for PciConfigMmio {
// Only allow reads to the register boundary.
let start = offset as usize % 4;
let end = start + data.len();
if end > 4 || offset > u64::from(u32::max_value()) {
if end > 4 || offset > u64::from(u32::MAX) {
for d in data {
*d = 0xff;
}
@@ -423,7 +423,7 @@ impl BusDevice for PciConfigMmio {
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if offset > u64::from(u32::max_value()) {
if offset > u64::from(u32::MAX) {
return None;
}
self.config_space_write(offset as u32, offset % 4, data);

View File

@@ -291,7 +291,7 @@ pub enum PciExpressCapabilityId {
VfResizeableBar = 0x0024,
DataLinkFeature = 0x0025,
PhysicalLayerSixteenGts = 0x0026,
LaneMargeningAtTheReceiver = 0x0027,
LaneMarginingAtTheReceiver = 0x0027,
HierarchyId = 0x0028,
NativePcieEnclosureManagement = 0x0029,
PhysicalLayerThirtyTwoGts = 0x002a,
@@ -345,7 +345,7 @@ impl From<u16> for PciExpressCapabilityId {
0x0024 => PciExpressCapabilityId::VfResizeableBar,
0x0025 => PciExpressCapabilityId::DataLinkFeature,
0x0026 => PciExpressCapabilityId::PhysicalLayerSixteenGts,
0x0027 => PciExpressCapabilityId::LaneMargeningAtTheReceiver,
0x0027 => PciExpressCapabilityId::LaneMarginingAtTheReceiver,
0x0028 => PciExpressCapabilityId::HierarchyId,
0x0029 => PciExpressCapabilityId::NativePcieEnclosureManagement,
0x002a => PciExpressCapabilityId::PhysicalLayerThirtyTwoGts,
@@ -743,7 +743,7 @@ impl PciConfiguration {
.ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
match config.region_type {
PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
if end_addr > u64::from(u32::max_value()) {
if end_addr > u64::from(u32::MAX) {
return Err(Error::BarAddressInvalid(config.addr, config.size));
}
@@ -757,10 +757,6 @@ impl PciConfiguration {
return Err(Error::BarInvalid64(bar_idx));
}
if end_addr > u64::max_value() {
return Err(Error::BarAddressInvalid(config.addr, config.size));
}
if self.bars[bar_idx + 1].used {
return Err(Error::BarInUse64(bar_idx));
}
@@ -818,7 +814,7 @@ impl PciConfiguration {
.checked_add(config.size - 1)
.ok_or(Error::RomBarAddressInvalid(config.addr, config.size))?;
if end_addr > u64::from(u32::max_value()) {
if end_addr > u64::from(u32::MAX) {
return Err(Error::RomBarAddressInvalid(config.addr, config.size));
}

View File

@@ -11,7 +11,7 @@ use std::fmt::{self, Display};
use std::sync::{Arc, Barrier, Mutex};
use std::{io, result};
use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::{BusDevice, Resource};
use vm_device::Resource;
#[derive(Debug)]
pub enum Error {
@@ -54,7 +54,7 @@ pub struct BarReprogrammingParams {
pub region_type: PciBarRegionType,
}
pub trait PciDevice: BusDevice {
pub trait PciDevice: Send {
/// Allocates the needed PCI BARs space using the `allocate` function which takes a size and
/// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples.
fn allocate_bars(
@@ -79,7 +79,7 @@ pub trait PciDevice: BusDevice {
/// Sets a register in the configuration space.
/// * `reg_idx` - The index of the config register to modify.
/// * `offset` - Offset in to the register.
/// * `offset` - Offset into the register.
fn write_config_register(
&mut self,
reg_idx: usize,
@@ -97,11 +97,11 @@ pub trait PciDevice: BusDevice {
) -> Option<BarReprogrammingParams> {
None
}
/// Reads from a BAR region mapped in to the device.
/// Reads from a BAR region mapped into the device.
/// * `addr` - The guest address inside the BAR.
/// * `data` - Filled with the data from `addr`.
fn read_bar(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {}
/// Writes to a BAR region mapped in to the device.
/// Writes to a BAR region mapped into the device.
/// * `addr` - The guest address inside the BAR.
/// * `data` - The data to write.
fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) -> Option<Arc<Barrier>> {

View File

@@ -213,6 +213,12 @@ impl MsixConfig {
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
if index >= self.table_entries.len() {
debug!("Invalid MSI-X table entry index {index}");
data.copy_from_slice(&[0xff; 8][..data.len()]);
return;
}
match data.len() {
4 => {
let value = match modulo_offset {
@@ -260,6 +266,11 @@ impl MsixConfig {
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
if index >= self.table_entries.len() {
debug!("Invalid MSI-X table entry index {index}");
return;
}
// Store the value of the entry before modification
let old_entry = self.table_entries[index].clone();
@@ -351,6 +362,12 @@ impl MsixConfig {
let index: usize = (offset / MSIX_PBA_ENTRIES_MODULO) as usize;
let modulo_offset = offset % MSIX_PBA_ENTRIES_MODULO;
if index >= self.pba_entries.len() {
debug!("Invalid MSI-X PBA entry index {index}");
data.copy_from_slice(&[0xff; 8][..data.len()]);
return;
}
match data.len() {
4 => {
let value: u32 = match modulo_offset {

View File

@@ -11,7 +11,6 @@ use std::any::Any;
use std::os::unix::prelude::AsRawFd;
use std::ptr::null_mut;
use std::sync::{Arc, Barrier, Mutex};
use std::u32;
use thiserror::Error;
use vfio_bindings::bindings::vfio::*;
use vfio_ioctls::VfioIrq;

View File

@@ -1,15 +1,15 @@
[package]
authors = ["The Cloud Hypervisor Authors"]
build = "../build.rs"
edition = "2021"
name = "performance-metrics"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
build = "../build.rs"
[dependencies]
clap = { version = "4.5.4", features = ["wrap_help"] }
dirs = "5.0.1"
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_json = "1.0.120"
test_infra = { path = "../test_infra" }
thiserror = "1.0.58"
thiserror = "1.0.62"
wait-timeout = "0.2.0"

View File

@@ -274,7 +274,7 @@ mod adjuster {
}
}
const TEST_LIST: [PerformanceTest; 29] = [
const TEST_LIST: [PerformanceTest; 30] = [
PerformanceTest {
name: "boot_time_ms",
func_ptr: performance_boot_time,
@@ -306,6 +306,16 @@ const TEST_LIST: [PerformanceTest; 29] = [
},
unit_adjuster: adjuster::s_to_ms,
},
PerformanceTest {
name: "restore_latency_time_ms",
func_ptr: performance_restore_latency,
control: PerformanceTestControl {
test_timeout: 2,
test_iterations: 10,
..PerformanceTestControl::default()
},
unit_adjuster: adjuster::identity,
},
PerformanceTest {
name: "boot_time_16_vcpus_pmem_ms",
func_ptr: performance_boot_time_pmem,

View File

@@ -23,6 +23,7 @@ pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-
enum Error {
BootTimeParse,
Infra(InfraError),
RestoreTimeParse,
}
impl From<InfraError> for Error {
@@ -34,7 +35,7 @@ impl From<InfraError> for Error {
const BLK_IO_TEST_IMG: &str = "/var/tmp/ch-blk-io-test.img";
pub fn init_tests() {
// The test image can not be created on tmpfs (e.g. /tmp) filesystem,
// The test image cannot be created on tmpfs (e.g. /tmp) filesystem,
// as tmpfs does not support O_DIRECT
assert!(exec_host_command_output(&format!(
"dd if=/dev/zero of={BLK_IO_TEST_IMG} bs=1M count=4096"
@@ -76,6 +77,26 @@ fn direct_kernel_boot_path() -> PathBuf {
kernel_path
}
fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool {
let mut cmd = std::process::Command::new(clh_command("ch-remote"));
cmd.args([&format!("--api-socket={}", api_socket), command]);
if let Some(arg) = arg {
cmd.arg(arg);
}
let output = cmd.output().unwrap();
if output.status.success() {
true
} else {
eprintln!(
"Error running ch-remote command: {:?}\nstderr: {}",
&cmd,
String::from_utf8_lossy(&output.stderr)
);
false
}
}
pub fn performance_net_throughput(control: &PerformanceTestControl) -> f64 {
let test_timeout = control.test_timeout;
let (rx, bandwidth) = control.net_control.unwrap();
@@ -199,7 +220,7 @@ fn parse_boot_time_output(output: &[u8]) -> Result<f64, Error> {
);
assert!(
t[7].eq("seconds"),
"Expecting 'seconds' as the the last word of the 'Debug I/O port' output"
"Expecting 'seconds' as the last word of the 'Debug I/O port' output"
);
t[6].parse::<f64>().unwrap()
@@ -226,7 +247,7 @@ fn parse_boot_time_output(output: &[u8]) -> Result<f64, Error> {
);
assert!(
t[7].eq("seconds"),
"Expecting 'seconds' as the the last word of the 'Debug I/O port' output"
"Expecting 'seconds' as the last word of the 'Debug I/O port' output"
);
t[6].parse::<f64>().unwrap()
@@ -255,7 +276,7 @@ fn measure_boot_time(cmd: &mut GuestCommand, test_timeout: u32) -> Result<f64, E
let _ = child.kill();
let output = child.wait_with_output().unwrap();
parse_boot_time_output(&output.stderr).map_err(|e| {
parse_boot_time_output(&output.stderr).inspect_err(|_| {
eprintln!(
"\n\n==== Start child stdout ====\n\n{}\n\n==== End child stdout ====",
String::from_utf8_lossy(&output.stdout)
@@ -264,8 +285,6 @@ fn measure_boot_time(cmd: &mut GuestCommand, test_timeout: u32) -> Result<f64, E
"\n\n==== Start child stderr ====\n\n{}\n\n==== End child stderr ====",
String::from_utf8_lossy(&output.stderr)
);
e
})
}
@@ -406,6 +425,120 @@ pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
}
}
// Parse the event_monitor file based on the format that each event
// is followed by a double newline
fn parse_event_file(event_file: &str) -> Vec<serde_json::Value> {
let content = fs::read(event_file).unwrap();
let mut ret = Vec::new();
for entry in String::from_utf8_lossy(&content)
.trim()
.split("\n\n")
.collect::<Vec<&str>>()
{
ret.push(serde_json::from_str(entry).unwrap());
}
ret
}
fn parse_restore_time_output(events: &[serde_json::Value]) -> Result<f64, Error> {
for entry in events.iter() {
if entry["event"].as_str().unwrap() == "restored" {
let duration = entry["timestamp"]["secs"].as_u64().unwrap() as f64 * 1_000f64
+ entry["timestamp"]["nanos"].as_u64().unwrap() as f64 / 1_000_000f64;
return Ok(duration);
}
}
Err(Error::RestoreTimeParse)
}
fn measure_restore_time(
cmd: &mut GuestCommand,
event_file: &str,
test_timeout: u32,
) -> Result<f64, Error> {
let mut child = cmd
.capture_output()
.verbosity(VerbosityLevel::Warn)
.set_print_cmd(false)
.spawn()
.unwrap();
thread::sleep(Duration::new((test_timeout / 2) as u64, 0));
let _ = child.kill();
let output = child.wait_with_output().unwrap();
let json_events = parse_event_file(event_file);
parse_restore_time_output(&json_events).inspect_err(|_| {
eprintln!(
"\n\n==== Start child stdout ====\n\n{}\n\n==== End child stdout ====\
\n\n==== Start child stderr ====\n\n{}\n\n==== End child stderr ====",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
)
})
}
pub fn performance_restore_latency(control: &PerformanceTestControl) -> f64 {
let r = std::panic::catch_unwind(|| {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = performance_test_new_guest(Box::new(focal));
let api_socket_source = String::from(
guest
.tmp_dir
.as_path()
.join("cloud-hypervisor.sock")
.to_str()
.unwrap(),
);
let mut child = GuestCommand::new(&guest)
.args(["--api-socket", &api_socket_source])
.args([
"--cpus",
&format!("boot={}", control.num_boot_vcpus.unwrap_or(1)),
])
.args(["--memory", "size=256M"])
.args(["--kernel", direct_kernel_boot_path().to_str().unwrap()])
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
.args(["--console", "off"])
.default_disks()
.set_print_cmd(false)
.spawn()
.unwrap();
thread::sleep(Duration::new((control.test_timeout / 2) as u64, 0));
let snapshot_dir = String::from(guest.tmp_dir.as_path().join("snapshot").to_str().unwrap());
std::fs::create_dir(&snapshot_dir).unwrap();
assert!(remote_command(&api_socket_source, "pause", None));
assert!(remote_command(
&api_socket_source,
"snapshot",
Some(format!("file://{}", snapshot_dir).as_str()),
));
let _ = child.kill();
let event_path = String::from(guest.tmp_dir.as_path().join("event.json").to_str().unwrap());
let mut cmd = GuestCommand::new(&guest);
let c = cmd
.args([
"--restore",
format!("source_url=file://{}", snapshot_dir).as_str(),
])
.args(["--event-monitor", format!("path={}", event_path).as_str()]);
measure_restore_time(c, event_path.as_str(), control.test_timeout).unwrap()
});
match r {
Ok(r) => r,
Err(_) => {
panic!("test failed!");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -496,7 +629,42 @@ cloud-hypervisor: 613.57361ms: <vcpu0> INFO:vmm/src/vm.rs:392 -- [Debug I/O port
assert_eq!(parse_boot_time_output(output.as_bytes()).unwrap(), 0.4525);
}
#[test]
fn test_parse_restore_time_output() {
let output = r#"
{
"timestamp": {
"secs": 0,
"nanos": 4664404
},
"source": "virtio-device",
"event": "activated",
"properties": {
"id": "__rng"
}
}
{
"timestamp": {
"secs": 0,
"nanos": 5505133
},
"source": "vm",
"event": "restored",
"properties": null
}
"#;
let mut ret = Vec::new();
for entry in String::from(output)
.trim()
.split("\n\n")
.collect::<Vec<&str>>()
{
ret.push(serde_json::from_str(entry).unwrap());
}
assert_eq!(parse_restore_time_output(&ret).unwrap(), 5.505133_f64);
}
#[test]
fn test_parse_fio_output() {
let output = r#"

View File

@@ -1,11 +1,11 @@
[package]
edition = "2021"
name = "rate_limiter"
version = "0.1.0"
edition = "2021"
[dependencies]
epoll = "4.3.3"
libc = "0.2.153"
log = "0.4.21"
thiserror = "1.0.58"
libc = "0.2.155"
log = "0.4.22"
thiserror = "1.0.62"
vmm-sys-util = "0.12.1"

View File

@@ -367,7 +367,7 @@ pub(crate) mod tests {
assert!(h.as_raw_fd() > 0);
// ops/s limiter should be disabled so consume(whatever) should work
assert!(h.consume(u64::max_value(), TokenType::Ops));
assert!(h.consume(u64::MAX, TokenType::Ops));
// do full 1000 bytes
assert!(h.consume(1000, TokenType::Bytes));
@@ -403,7 +403,7 @@ pub(crate) mod tests {
assert!(h.as_raw_fd() > 0);
// bytes/s limiter should be disabled so consume(whatever) should work
assert!(h.consume(u64::max_value(), TokenType::Bytes));
assert!(h.consume(u64::MAX, TokenType::Bytes));
// do full 1000 ops
assert!(h.consume(1000, TokenType::Ops));

View File

@@ -307,14 +307,14 @@ impl RateLimiter {
///
/// * `bytes_total_capacity` - the total capacity of the `TokenType::Bytes` token bucket.
/// * `bytes_one_time_burst` - initial extra credit on top of `bytes_total_capacity`,
/// that does not replenish and which can be used for an initial burst of data.
/// that does not replenish and which can be used for an initial burst of data.
/// * `bytes_complete_refill_time_ms` - number of milliseconds for the `TokenType::Bytes`
/// token bucket to go from zero Bytes to `bytes_total_capacity` Bytes.
/// token bucket to go from zero Bytes to `bytes_total_capacity` Bytes.
/// * `ops_total_capacity` - the total capacity of the `TokenType::Ops` token bucket.
/// * `ops_one_time_burst` - initial extra credit on top of `ops_total_capacity`,
/// that does not replenish and which can be used for an initial burst of data.
/// that does not replenish and which can be used for an initial burst of data.
/// * `ops_complete_refill_time_ms` - number of milliseconds for the `TokenType::Ops` token
/// bucket to go from zero Ops to `ops_total_capacity` Ops.
/// bucket to go from zero Ops to `ops_total_capacity` Ops.
///
/// If either bytes/ops *size* or *refill_time* are **zero**, the limiter
/// is **disabled** for that respective token type.
@@ -662,8 +662,8 @@ pub(crate) mod tests {
// limiter should not be blocked
assert!(!l.is_blocked());
// limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Ops));
assert!(l.consume(u64::max_value(), TokenType::Bytes));
assert!(l.consume(u64::MAX, TokenType::Ops));
assert!(l.consume(u64::MAX, TokenType::Bytes));
// calling the handler without there having been an event should error
assert!(l.event_handler().is_err());
assert_eq!(
@@ -721,7 +721,7 @@ pub(crate) mod tests {
assert!(l.as_raw_fd() > 0);
// ops/s limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Ops));
assert!(l.consume(u64::MAX, TokenType::Ops));
// do full 1000 bytes
assert!(l.consume(1000, TokenType::Bytes));
@@ -754,7 +754,7 @@ pub(crate) mod tests {
assert!(l.as_raw_fd() > 0);
// bytes/s limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Bytes));
assert!(l.consume(u64::MAX, TokenType::Bytes));
// do full 1000 ops
assert!(l.consume(1000, TokenType::Ops));

View File

@@ -1,10 +1,20 @@
- [v41.0](#v410)
- [Experimental "Pvmemcontrol" Support](#experimental-pvmemcontrol-support)
- [Sandboxing With Landlock Support](#sandboxing-with-landlock-support)
- [Notable Performance Improvements](#notable-performance-improvements)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [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-1)
- [Contributors](#contributors-1)
- [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)
- [Contributors](#contributors)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-2)
- [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)
@@ -12,16 +22,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-1)
- [Contributors](#contributors-1)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-3)
- [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-2)
- [Contributors](#contributors-2)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-4)
- [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)
@@ -30,31 +40,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-3)
- [Contributors](#contributors-3)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [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-4)
- [Contributors](#contributors-4)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [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-5)
- [Contributors](#contributors-5)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [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-6)
- [Contributors](#contributors-6)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [v32.0](#v320)
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
- [API Changes](#api-changes)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [v31.1](#v311)
- [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
@@ -62,15 +72,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-8)
- [Contributors](#contributors-8)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Contributors](#contributors-10)
- [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-9)
- [Contributors](#contributors-9)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Contributors](#contributors-11)
- [v28.2](#v282)
- [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
@@ -80,10 +90,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-10)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Removals](#removals)
- [Deprecations](#deprecations)
- [Contributors](#contributors-10)
- [Contributors](#contributors-12)
- [v28.1](#v281)
- [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder)
@@ -91,9 +101,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-11)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Removals](#removals-1)
- [Contributors](#contributors-11)
- [Contributors](#contributors-13)
- [v27.0](#v270)
- [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages)
@@ -102,41 +112,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-12)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-12)
- [Contributors](#contributors-14)
- [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-13)
- [Notable Bug Fixes](#notable-bug-fixes-15)
- [Deprecations](#deprecations-2)
- [Removals](#removals-2)
- [Contributors](#contributors-13)
- [Contributors](#contributors-15)
- [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Removals](#removals-3)
- [Contributors](#contributors-14)
- [Contributors](#contributors-16)
- [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-15)
- [Notable Bug Fixes](#notable-bug-fixes-17)
- [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website)
- [Contributors](#contributors-15)
- [Contributors](#contributors-17)
- [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-16)
- [Notable Bug Fixes](#notable-bug-fixes-18)
- [Deprecations](#deprecations-4)
- [Contributors](#contributors-16)
- [Contributors](#contributors-18)
- [v22.1](#v221)
- [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support)
@@ -147,13 +157,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-17)
- [Contributors](#contributors-17)
- [Notable Bug Fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-19)
- [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-18)
- [Contributors](#contributors-18)
- [Notable Bug fixes](#notable-bug-fixes-20)
- [Contributors](#contributors-20)
- [v20.2](#v202)
- [v20.1](#v201)
- [v20.0](#v200)
@@ -162,8 +172,8 @@
- [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code)
- [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-19)
- [Notable bug fixes](#notable-bug-fixes-21)
- [Contributors](#contributors-21)
- [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)
@@ -171,8 +181,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-20)
- [Contributors](#contributors-20)
- [Notable bug fixes](#notable-bug-fixes-22)
- [Contributors](#contributors-22)
- [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)
@@ -182,23 +192,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-21)
- [Contributors](#contributors-21)
- [Notable bug fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-23)
- [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-22)
- [Contributors](#contributors-22)
- [Notable bug fixes](#notable-bug-fixes-24)
- [Contributors](#contributors-24)
- [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-23)
- [Notable bug fixes](#notable-bug-fixes-25)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors-23)
- [Contributors](#contributors-25)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@@ -206,7 +216,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5)
- [Contributors](#contributors-24)
- [Contributors](#contributors-26)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@@ -216,7 +226,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-25)
- [Contributors](#contributors-27)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@@ -224,13 +234,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-26)
- [Contributors](#contributors-28)
- [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-27)
- [Contributors](#contributors-29)
- [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)
@@ -242,15 +252,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-24)
- [Contributors](#contributors-28)
- [Notable Bug Fixes](#notable-bug-fixes-26)
- [Contributors](#contributors-30)
- [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-25)
- [Contributors](#contributors-29)
- [Notable Bug Fixes](#notable-bug-fixes-27)
- [Contributors](#contributors-31)
- [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)
@@ -263,17 +273,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-26)
- [Contributors](#contributors-30)
- [Notable Bug Fixes](#notable-bug-fixes-28)
- [Contributors](#contributors-32)
- [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-27)
- [Notable Bug Fixes](#notable-bug-fixes-29)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-31)
- [Contributors](#contributors-33)
- [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)
@@ -283,14 +293,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-32)
- [Contributors](#contributors-34)
- [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-33)
- [Contributors](#contributors-35)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -298,7 +308,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-34)
- [Contributors](#contributors-36)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -307,7 +317,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-35)
- [Contributors](#contributors-37)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@@ -334,6 +344,116 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# 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:
### Experimental "Pvmemcontrol" Support
VMM support has been added for this experimental functionality (requires
currently out of tree Linux kernel patches) to allow guests to control its
physical memory properties to allow optimisations and security features.
(#6318, #6467)
### Sandboxing With Landlock Support
Support for restricting the VMM process using the Linux kernel "Landlock" API
has been added - this can be used to restrict the files (and the read/write
permissions) that the VMM process can access. This adds another layer of
security alongside the existing sycall filters (`seccomp`) - this can be
enabled with `--landlock` and [fully documentated](docs/landlock.md). (#5170)
### Notable Performance Improvements
* Reduced heap allocations in `virtio-net` via the use of a cache of `Iovec`
structures (#6636)
* Notification suppression ("`EVENT_IDX`") support has been added to
`virtio-block` giving a 60% improvement in single queue block throughput and
IOPs performance (#6580)
* Correct size used for `status` field in `virtio-block` state (#6586)
### Notable Bug Fixes
* Avoid panic on out-of-bounds PCI MSI-X access (#6657)
* Fix undefined behaviour on AArch64 leading to wrong optimisation on KVM API
access (#6647)
* Rust v1.80.0 added use of `fcntl` syscall on debug assertions so this is now
included in the virtio-device seccomp filters for tests that use this (#6648)
* Short reads are now handled correctly in the `virtio-vsock` device (#6621)
* Fix undefined behaviour on TTY ioctl leading to wrong optimisation (#6568)
### Contributors
Many thanks to everyone who has contributed to our release:
* Alyssa Ross <hi@alyssa.is>
* Bo Chen <chen.bo@intel.com>
* Changyuan Lyu <changyuanl@google.com>
* Jinank Jain <jinankjain@microsoft.com>
* Julian Stecklina <julian.stecklina@cyberus-technology.de>
* Muminul Islam <muislam@microsoft.com>
* Nuno Das Neves <nudasnev@microsoft.com>
* Praveen K Paladugu <prapal@linux.microsoft.com>
* Rob Bradford <rbradford@rivosinc.com>
* Songqian Li <sionli@tencent.com>
* Wei Liu <liuwe@microsoft.com>
* Yuanchu Xie <yuanchu@google.com>
* ihciah <ihciah@gmail.com>
* wuxinyue <wuxinyue.wxy@antgroup.com>
# 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:
### Support for Restoring File Descriptor Backed Network Devices
It is now possible to pass file descriptors over the HTTP API (and using
`ch-remote`) when restoring to update the file descriptors for network devices.
This enables snapshot & restore functionality for guests using `macvtap` or
other file descriptor backed network devices. (#6286)
### Notable Bug Fixes
* Default values have been removed from required fields in the OpenAPI metadata
(#6495)
* The help syntax of `ch-remote remove-device` has been improved (#6456)
* A double close of file descriptors has been fixed when using `--serial`
(#6486)
* To prevent loops a limit on the nesting level for QCOW2 backing files has
been introduced (#6482)
* Boot time performance has been improved with multiple cores by avoiding
`cpuid` instructions and by seeding the in kernel file descriptor table
(#6498, #6478)
* L1 cache details are more likely to be propagated into the guest (#6523)
* The default topology for guests now uses multiple cores rather than sockets
(#6504)
### Contributors
Many thanks to everyone who has contributed to our release:
* Alexandru Matei <alexandru.matei@uipath.com>
* Bo Chen <chen.bo@intel.com>
* Jinank Jain <jinankjain@microsoft.com>
* Josh Soref <2119212+jsoref@users.noreply.github.com>
* Muminul Islam <muislam@microsoft.com>
* Nuno Das Neves <nudasnev@microsoft.com>
* Omer Faruk Bayram <omer.faruk@sartura.hr>
* Praveen K Paladugu <prapal@linux.microsoft.com>
* Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
* Rob Bradford <rbradford@rivosinc.com>
* SamrutGadde <samrut.gadde@gmail.com>
* Sean Banko <sbanko@crusoe.ai>
* Songqian Li <sionli@tencent.com>
* Wei Liu <liuwe@microsoft.com>
* Yi Wang <foxywang@tencent.com>
* Yu Li <liyu.yukiteru@bytedance.com>
*
# v39.0
This release has been tracked in our [roadmap
@@ -1081,7 +1201,7 @@ releases of the LTS.
### Virtualised TPM Support
Support for adding an emulated CRB TPM has been added. This has it's own [TPM
Support for adding an emulated CRB TPM has been added. This has its own [TPM
documentation](docs/tpm.md).
### Transparent Huge Page Support
@@ -1272,7 +1392,7 @@ plan to use alternatives.
The following functionality has been removed:
* The unused `poll_queue` parameter has been removed from `--disk` and
equivalent. This was residual from the the removal of the `vhost-user-block`
equivalent. This was residual from the removal of the `vhost-user-block`
spawning feature (#4402.)
### Contributors
@@ -2094,19 +2214,19 @@ Deprecated features will be removed in a subsequent release and users should pla
Many thanks to everyone who has contributed to our 0.14.0 release including
some new faces.
Bo Chen <chen.bo@intel.com>
Henry Wang <Henry.Wang@arm.com>
Iggy Jackson <iggy@theiggy.com>
Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
Michael Zhao <michael.zhao@arm.com>
Muminul Islam <muislam@microsoft.com>
Penny Zheng <Penny.Zheng@arm.com>
Rob Bradford <robert.bradford@intel.com>
Sebastien Boeuf <sebastien.boeuf@intel.com>
Vineeth Pillai <viremana@linux.microsoft.com>
Wei Liu <liuwe@microsoft.com>
William Douglas <william.r.douglas@gmail.com>
Zide Chen <zide.chen@intel.com>
* Bo Chen <chen.bo@intel.com>
* Henry Wang <Henry.Wang@arm.com>
* Iggy Jackson <iggy@theiggy.com>
* Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
* Michael Zhao <michael.zhao@arm.com>
* Muminul Islam <muislam@microsoft.com>
* Penny Zheng <Penny.Zheng@arm.com>
* Rob Bradford <robert.bradford@intel.com>
* Sebastien Boeuf <sebastien.boeuf@intel.com>
* Vineeth Pillai <viremana@linux.microsoft.com>
* Wei Liu <liuwe@microsoft.com>
* William Douglas <william.r.douglas@gmail.com>
* Zide Chen <zide.chen@intel.com>
# v0.13.0
@@ -2191,7 +2311,7 @@ removed.
### Migration of `vhost-user-fs` backend
The `vhost-user-fs` backend is no longer included in Cloud Hypervisor and it is
instead hosted in [it's own
instead hosted in [its own
repository](https://gitlab.com/virtio-fs/virtiofsd-rs)
### Enhanced "info" API
@@ -2325,7 +2445,7 @@ Some `virtio-block` device drivers may generate requests with multiple descripto
### Memory Zones
Support has been added for fine grained control of memory allocation for the guest. This includes controlling the backing of sections of guest memory, assigning to specific host NUMA nodes and assigning memory and vCPUs to specific memory nodes inside the guest. Full details of this can be found in the [memory documentation](docs/memory.md).
Support has been added for fine-grained control of memory allocation for the guest. This includes controlling the backing of sections of guest memory, assigning to specific host NUMA nodes and assigning memory and vCPUs to specific memory nodes inside the guest. Full details of this can be found in the [memory documentation](docs/memory.md).
### `Seccomp` Sandbox Improvements

View File

@@ -8,7 +8,7 @@
FROM ubuntu:22.04 as dev
ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.74.1"
ARG RUST_TOOLCHAIN="1.77.0"
ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"

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="20240407-0"
CTR_IMAGE_VERSION="20240507-0"
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
DOCKER_RUNTIME="docker"

View File

@@ -134,7 +134,7 @@ update_workloads() {
popd || exit
# Download Cloud Hypervisor binary from its last stable release
LAST_RELEASE_VERSION="v36.0"
LAST_RELEASE_VERSION="v39.0"
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
pushd "$WORKLOADS_DIR" || exit

View File

@@ -45,7 +45,7 @@ fi
popd || exit
# Download Cloud Hypervisor binary from its last stable release
LAST_RELEASE_VERSION="v36.0"
LAST_RELEASE_VERSION="v39.0"
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
CH_RELEASE_NAME="cloud-hypervisor-static"
pushd "$WORKLOADS_DIR" || exit

View File

@@ -3,7 +3,7 @@
set -x
# This set of vfio tests require to be ran on a specific machine with
# specific hardware (e.g. the "vfio" bera-metal worker equipped with a
# specific hardware (e.g. the "vfio" bare-metal worker equipped with a
# Nvidia Tesla T4 card). So the provisioning of the running machine is
# out of the scope of this script, including the custom guest image with
# Nvidia drivers installed, and properly configured Nvidia Tesla T4 card.

View File

@@ -1,5 +1,5 @@
[package]
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
name = "serial_buffer"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"

View File

@@ -15,7 +15,7 @@ use std::marker::PhantomData;
use std::os::unix::net::UnixStream;
use std::process;
#[cfg(feature = "dbus_api")]
use zbus::{dbus_proxy, zvariant::Optional};
use zbus::{proxy, zvariant::Optional};
type ApiResult = Result<(), Error>;
@@ -72,7 +72,7 @@ enum TargetApi<'a> {
}
#[cfg(feature = "dbus_api")]
#[dbus_proxy(name = "org.cloudhypervisor.DBusApi1", assume_defaults = false)]
#[proxy(name = "org.cloudhypervisor.DBusApi1", assume_defaults = false)]
trait DBusApi1 {
fn vmm_ping(&self) -> zbus::Result<String>;
fn vmm_shutdown(&self) -> zbus::Result<()>;
@@ -445,14 +445,14 @@ fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResu
.map_err(Error::HttpApiClient)
}
Some("restore") => {
let restore_config = restore_config(
let (restore_config, fds) = restore_config(
matches
.subcommand_matches("restore")
.unwrap()
.get_one::<String>("restore_config")
.unwrap(),
)?;
simple_api_command(socket, "PUT", "restore", Some(&restore_config))
simple_api_command_with_fds(socket, "PUT", "restore", Some(&restore_config), fds)
.map_err(Error::HttpApiClient)
}
Some("coredump") => {
@@ -661,7 +661,7 @@ fn dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>)
proxy.api_vm_snapshot(&snapshot_config)
}
Some("restore") => {
let restore_config = restore_config(
let (restore_config, _fds) = restore_config(
matches
.subcommand_matches("restore")
.unwrap()
@@ -849,11 +849,20 @@ fn snapshot_config(url: &str) -> String {
serde_json::to_string(&snapshot_config).unwrap()
}
fn restore_config(config: &str) -> Result<String, Error> {
let restore_config = vmm::config::RestoreConfig::parse(config).map_err(Error::Restore)?;
fn restore_config(config: &str) -> Result<(String, Vec<i32>), Error> {
let mut restore_config = vmm::config::RestoreConfig::parse(config).map_err(Error::Restore)?;
// RestoreConfig is modified on purpose to take out the file descriptors.
// These fds are passed to the server side process via SCM_RIGHTS
let fds = match &mut restore_config.net_fds {
Some(net_fds) => net_fds
.iter_mut()
.flat_map(|net| net.fds.take().unwrap_or_default())
.collect(),
None => Vec::new(),
};
let restore_config = serde_json::to_string(&restore_config).unwrap();
Ok(restore_config)
Ok((restore_config, fds))
}
fn coredump_config(destination_url: &str) -> String {
@@ -987,7 +996,7 @@ fn main() {
)
.subcommand(
Command::new("remove-device")
.about("Remove VFIO device")
.about("Remove VFIO and PCI device")
.arg(Arg::new("id").index(1).help("<device_id>")),
)
.subcommand(Command::new("info").about("Info on the VM"))

View File

@@ -12,17 +12,18 @@ use log::{warn, LevelFilter};
use option_parser::OptionParser;
use seccompiler::SeccompAction;
use signal_hook::consts::SIGSYS;
use std::env;
use std::fs::File;
use std::os::unix::io::{FromRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
use std::{env, io};
use thiserror::Error;
#[cfg(feature = "dbus_api")]
use vmm::api::dbus::{dbus_api_graceful_shutdown, DBusApiOptions};
use vmm::api::http::http_api_graceful_shutdown;
use vmm::api::ApiAction;
use vmm::config;
use vmm::landlock::{Landlock, LandlockError};
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::signal::block_signal;
@@ -85,6 +86,22 @@ enum Error {
LoggerSetup(log::SetLoggerError),
#[error("Failed to gracefully shutdown http api: {0}")]
HttpApiShutdown(#[source] vmm::Error),
#[error("Failed to create Landlock object: {0}")]
CreateLandlock(#[source] LandlockError),
#[error("Failed to apply Landlock: {0}")]
ApplyLandlock(#[source] LandlockError),
}
#[derive(Error, Debug)]
enum FdTableError {
#[error("Failed to create event fd: {0}")]
CreateEventFd(std::io::Error),
#[error("Failed to obtain file limit: {0}")]
GetRLimit(std::io::Error),
#[error("Error calling fcntl with F_GETFD: {0}")]
GetFd(std::io::Error),
#[error("Failed to duplicate file handle: {0}")]
Dup2(std::io::Error),
}
struct Logger {
@@ -259,6 +276,24 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.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(config::LandlockConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("net")
.long("net")
@@ -487,6 +522,16 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.num_args(1)
.group("vm-config"),
);
#[cfg(feature = "pvmemcontrol")]
let app = app.arg(
Arg::new("pvmemcontrol")
.long("pvmemcontrol")
.help("Pvmemcontrol device")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
);
app.arg(
Arg::new("version")
.short('V')
@@ -622,6 +667,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
let landlock_enable = cmd_arguments.get_flag("landlock");
#[allow(unused_mut)]
let mut event_monitor = cmd_arguments
@@ -691,6 +737,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
vmm::start_event_monitor_thread(
monitor,
&seccomp_action,
landlock_enable,
hypervisor.hypervisor_type(),
exit_evt.try_clone().unwrap(),
)
@@ -717,6 +764,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
exit_evt.try_clone().unwrap(),
&seccomp_action,
hypervisor,
landlock_enable,
)
.map_err(Error::StartVmmThread)?;
@@ -764,6 +812,13 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
}
}
if landlock_enable {
Landlock::new()
.map_err(Error::CreateLandlock)?
.restrict_self()
.map_err(Error::ApplyLandlock)?;
}
vmm_thread_handle
.thread_handle
.join()
@@ -782,6 +837,77 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
r.map(|_| api_socket_path)
}
// This is a best-effort solution to the latency induced by the RCU
// synchronization that happens in the kernel whenever the file descriptor table
// fills up.
// The table has initially 64 entries on amd64 and every time it fills up, a new
// table is created, double the size of the current one, and the entries are
// copied to the new table. The filesystem code that does this uses
// synchronize_rcu() to ensure all preexisting RCU read-side critical sections
// have completed:
//
// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/fs/file.c?h=v6.9.1#n162
//
// Rust programs that create lots of file handles or use
// {File,EventFd}::try_clone() to share them are impacted by this issue. This
// behavior is quite noticeable in the snapshot restore scenario, the latency is
// a big chunk of the total time required to start cloud-hypervisor and restore
// the snapshot.
//
// The kernel has an optimization in code, where it doesn't call
// synchronize_rcu() if there is only one thread in the process. We can take
// advantage of this optimization by expanding the descriptor table at
// application start, when it has only one thread.
//
// The code tries to resize the table to an adequate size for most use cases,
// 4096, this way we avoid any expansion that might take place later.
fn expand_fdtable() -> Result<(), FdTableError> {
let mut limits = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
// SAFETY: FFI call with valid arguments
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut limits) } < 0 {
return Err(FdTableError::GetRLimit(io::Error::last_os_error()));
}
let table_size = if limits.rlim_cur == libc::RLIM_INFINITY {
4096
} else {
std::cmp::min(limits.rlim_cur, 4096) as libc::c_int
};
// The first 3 handles are stdin, stdout, stderr. We don't want to touch
// any of them.
if table_size <= 3 {
return Ok(());
}
let dummy_evt = EventFd::new(0).map_err(FdTableError::CreateEventFd)?;
// Test if the file descriptor is empty
// SAFETY: FFI call with valid arguments
let flags: i32 = unsafe { libc::fcntl(table_size - 1, libc::F_GETFD) };
if flags >= 0 {
// Nothing to do, the table is already big enough
return Ok(());
}
let err = io::Error::last_os_error();
if err.raw_os_error() != Some(libc::EBADF) {
return Err(FdTableError::GetFd(err));
}
// SAFETY: FFI call with valid arguments
if unsafe { libc::dup2(dummy_evt.as_raw_fd(), table_size - 1) } < 0 {
return Err(FdTableError::Dup2(io::Error::last_os_error()));
}
// SAFETY: FFI call, trivially
unsafe { libc::close(table_size - 1) };
Ok(())
}
fn main() {
#[cfg(all(feature = "tdx", feature = "sev_snp"))]
compile_error!("Feature 'tdx' and 'sev_snp' are mutually exclusive.");
@@ -808,6 +934,10 @@ fn main() {
return;
}
if let Err(e) = expand_fdtable() {
warn!("Error expanding FD table: {e}");
}
let exit_code = match start_vmm(cmd_arguments) {
Ok(path) => {
path.map(|s| std::fs::remove_file(s).ok());
@@ -934,6 +1064,8 @@ mod unit_tests {
vdpa: None,
vsock: None,
pvpanic: false,
#[cfg(feature = "pvmemcontrol")]
pvmemcontrol: None,
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
@@ -945,6 +1077,8 @@ mod unit_tests {
platform: None,
tpm: None,
preserved_fds: None,
landlock_enable: false,
landlock_rules: None,
};
assert_eq!(expected_vm_config, result_vm_config);

View File

@@ -1,16 +1,16 @@
[package]
name = "test_infra"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
name = "test_infra"
version = "0.1.0"
[dependencies]
dirs = "5.0.1"
epoll = "4.3.3"
libc = "0.2.153"
libc = "0.2.155"
once_cell = "1.19.0"
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_json = "1.0.120"
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
vmm-sys-util = "0.12.1"
wait-timeout = "0.2.0"

Some files were not shown because too many files have changed in this diff Show More