Compare commits

...

534 Commits
v44.0 ... v49.0

Author SHA1 Message Date
Bo Chen
9acf610a7b build: Release v49.0
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-11-08 04:05:16 +00:00
Aastha Rawat
c4cce38631 scripts: aarch64: replace guestmount for image modification
Replace the use of `guestmount and `guestunmount` with standard tools
(losetup, mount) to modify cloud disk image. This eliminates
dependency on guestmount which requires /dev/kvm and is not available
in MSHV root partition.

Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
2025-11-06 19:33:53 +00:00
Aastha Rawat
e302d50b09 scripts: aarch64: enable MSHV support
Refactor MSHV hypervisor selection logic to enable aarch64 support
instead of exiting. Use `--features mshv` to conditionally build &
test when hypervisor is mshv replacing hard exit for aarch64 on mshv.

Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
2025-11-06 19:33:53 +00:00
Eugene Korenevsky
3791062b23 block: qcow: refactor: extract method cache_l2_cluster()
There are several copy-pasted code fragments in impl QcowFile. All of
them add L2 entry to the cache and one of them (in file_offset_write())
does also allocating new L2 entry if necessary.

Fold all these code fragments (except of one in l2_table() which does
error handling in special way) into cache_l2_cluster() method without
changing the logic.
This will make the code more compact and clean.

Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
2025-11-05 16:58:24 +00:00
Muminul Islam
e3fa27e251 scripts: Fix issue when extra docker volumes provided
With the current syntax docker gives 'docker: invalid reference format'
error. Also during parsing /xxx:/yyy in process_volumes_args
with \" inside variable i.e arr_vols=("${arg_vols//#/ }")
gives wrong output.

Example:
scripts/dev_cli.sh tests --integration --volumes /mshv:/mshv
Error: The volume /mshv /mshv does not exist.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-11-05 10:45:24 +00:00
Rob Bradford
932e1a636a tests: Disable integration tests that use virtio-mem on MSHV
These tests are now failing

See: #7456

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-11-04 19:44:02 +00:00
Alyssa Ross
d59dfdf8b6 vmm: seccomp: allow http-server to use sendto
Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7449
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-11-03 12:41:18 +00:00
Ariel Chenet
9158c36dbf docs: Update documentation to reflect initial VMM output
The API documentation tells users to expect a message when Cloud
Hypervisor is launched, this message was removed in commit 13724db

This change updates the documentation to reflect how the program
actually functions, which is to say no message.

Signed-off-by: Ariel Chenet <achenet@fastmail.com>
2025-11-03 10:30:05 +00:00
dependabot[bot]
2a39b4a4e5 build: Bump crate-ci/typos from 1.38.1 to 1.39.0
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.38.1 to 1.39.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.38.1...v1.39.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-01 00:03:30 +00:00
Alyssa Ross
0395b10b29 openapi: add missing NetConfig offload parameters
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-10-30 18:40:07 +00:00
Alyssa Ross
1356b26c0f build: bump bitfield-struct from 0.11.0 to 0.12.1
Should fix beta clippy.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-10-30 00:40:50 +00:00
Philipp Schuster
7536a95424 misc: cleanup &Arc<dyn T> -> &dyn T
Consuming `&Arc<T>` as argument is almost always an antipattern as it
hides whether the callee is going to take over (shared) ownership
(by .clone()) or not. Instead, it is better to consume `&dyn T` or
`Arc<dyn T>` to be more explicit. This commit cleans up the code.

The change is very mechanic and was very easy to implement across the
code base.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-28 17:37:49 +00:00
Anirudh Rayabharam
e295719967 tests: disable test_snapshot_restore_hotplug_virtiomem for mshv
Disable test_snapshot_restore_hotplug_virtiomem for mshv. It is failing
frequently in the CI. It needs to be stabilized before enabling again.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-28 15:31:58 +00:00
Anirudh Rayabharam
6198fa7a79 tests: disable broken ivshmem tests for MSHV
The ivshmem tests involving snapshot/restore & live migration are
failing in the MSHV CI with this error:

Could not get vCPU state GetMsrEntries(
  Hypercall 80 failed with 0x5 : InvalidParameter ...<snip>)

This needs more investigation. It is worth noting that the general live
migration tests are also not run in the CI for MSHV.

Disable these tests for MSHV for the time being.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-28 15:31:58 +00:00
Anirudh Rayabharam
f74cde7882 scripts: build mshv feature for ivshmem testing
The ivshmem tests are all failing in the CI for MSHV because Cloud
Hypervisor is built without the mshv feature.

Error: Cloud Hypervisor exited with the following chain of errors:
  0: Failed to open hypervisor interface (is hypervisor interface
       available?)
  1: Failed to create the hypervisor
  2: no supported hypervisor

Modify the build command to include the mshv feature.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-28 15:31:58 +00:00
AASTHA RAWAT
f033c5837b ci: prevent cross-PR CI cancellation for mshv workflows
The existing concurrency configuration causes workflow runs for one Pull
Request to cancel in-progress runs for another Pull Request. When the
workflow is triggered by the `pull_request_target event`, `github.ref`
is always set to the base branch, regardless of which branch raised the
PR. This causes every new pull request to share the same concurrency key
and thus cancel the running CI of any other open pull request.

This commit updates the `concurrency.group` to use
`github.event.pull_request.number` for unique isolation when running on
PR, falling back to `github.ref` for non-PR push (e.g., merge group).

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-27 12:43:08 +00:00
AASTHA RAWAT
03349e7523 tests: disable skipped integration tests for mshv
Disable the following common parallel and common sequential tests for
mshv since these are failing consistently in the CI.

Common parallel:
- test_tpm
- test_cpu_topology_421
- test_cpu_topology_142
- test_cpu_topology_262
- test_cpu_hotplug

Common sequential:
- test_snapshot_restore_basic
- test_snapshot_restore_with_fd
- test_snapshot_restore_pvpanic

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-25 12:57:16 +01:00
AASTHA RAWAT
5d9f75ca6d ci: remove skipped tests from integration workflow
Move the list of skipped tests from integration test workflow for
mshv.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-25 12:57:16 +01:00
Anirudh Rayabharam
861b7ab64d tests: exclude test_fw_cfg for mshv
test_fw_cfg is frequently failing in the CI for MSHV. Exclude it for
now. It needs further investigation. See issue #7434 for details.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-25 10:16:24 +00:00
dependabot[bot]
fe32002141 build: Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-24 23:58:01 +00:00
Anirudh Rayabharam
3e339439a4 arch: move GICv2M SPI base to leave room for legacy IRQs
Move the GICv2M MSI frame SPI base from 32 to 128 to avoid conflicts
with platform device interrupts.

While at it, rename the constants to make it explicit that they are
associated with the GICv2m MSI Frame.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-24 17:11:35 +00:00
Rob Bradford
cb5aaca809 hypervisor, vmm: Remove inner Mutex protecting VcpuFd
This was added in 7be69edf51 to deal with
changes to the KVM bindings that made run() and set_immediate_exit()
take &mut self. Instead adopt a Box<> value in Vcpu allowing the removal
of this internal Mutex.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-24 13:13:12 +00:00
dependabot[bot]
0a25a77095 build: Bump crate-ci/typos from 1.38.0 to 1.38.1
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.38.0 to 1.38.1.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.38.0...v1.38.1)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.38.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-23 00:03:36 +00:00
Rob Bradford
7d6c450cee virtio-devices: pci_common_config: Remove warning for feature pages > 2
The virtio spec defines the feature bit range and 4 x 32-bit pages.
However no features are currently defined with bits > 63. However Linux
has now started acking features in those higher pages. Since this is
harmless (we drop the acks to those feature pages) and quietly return 0
for available features in those higher pages this warning can be
removed.

Fixes: #7414

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-22 08:39:56 +00:00
Philipp Schuster
d39b56544a vmm: fix CpuManager::resume(): gracefully wait for run vCPU loop ACK
Fix a race condition that happens in resume()-pause() cycles.

It is odd that for pause(), the CpuManager waited via `state.paused`
for the vCPU thread to ACK the state change but not for `resume()`.
In the `resume()` case, oddly CpuManager "owned" the state change
in `state.paused`. This commit changes this so that the vCPU ACKs
its state change itself in `state.paused` when it transitions from
pause->run. Further, `CpuManager::resume()` now gracefully waits for
the vCPU to be resumed.

More technical:

This change ensures proper synchronization and prevents situations
in that park() follows right after unpark(), causing deadlocks and
other weird behavior due to race conditions.

Calling resume() now takes slightly longer, very similar to pause().
This is, however, even for 254 vCPUs in the range of less than 10ms,
and ultimately we now have correct behaviour.

## Reproducer

Since [0] is merged, the underlying problem can be tested without this
commit by modifying the pause() API call to run `CpuManager::pause()`
and `CpuManager::resume()` in a loop a thousand times.

`ch-remote --api-socket ... pause`

```patch
diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs
index d7bba25cc..35557d58f 100644
--- a/vmm/src/vm.rs
+++ b/vmm/src/vm.rs
@@ -2687,6 +2687,10 @@ impl Pausable for Vm {
             MigratableError::Pause(anyhow!("Error activating pending virtio devices: {:?}", e))
         })?;

+        for _ in 0..1000 {
+            self.cpu_manager.lock().unwrap().pause()?;
+            self.cpu_manager.lock().unwrap().resume()?;
+        }
         self.cpu_manager.lock().unwrap().pause()?;
         self.device_manager.lock().unwrap().pause()?;
```

## Outlook

Decades of experience in VMM development showed us that using
many AtomicBools is a footgun. They are not synchronized with each
other at all. On the long term, we might want to refactor things to
have a single shared AtomicU64 with different bits having different
meanings.

[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7290

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-22 07:54:08 +00:00
Philipp Schuster
8481026b60 vmm: refactor poor naming
These bindings actually refer to atomic bool shared across all
vCPUs to instruct single vCPUs with their next action. As there
are already enough Arc<AtomicBool>, this helps while debugging
things to see that different bindings refer to the same atomic
bool.

In other words: This naming really confused us while debugging.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-22 07:54:08 +00:00
Philipp Schuster
e6ddfe07c3 vmm: remove noop
The vCPU lifecycle is already complicated. Let's remove dead
code (the impl is a no-op).

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-22 07:54:08 +00:00
dependabot[bot]
221cbeba5a build: Bump fsfe/reuse-action from 5 to 6
Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 5 to 6.
- [Release notes](https://github.com/fsfe/reuse-action/releases)
- [Commits](https://github.com/fsfe/reuse-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: fsfe/reuse-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-22 10:24:42 +01:00
Rob Bradford
99d08a2b7f tests: Replace fixed wait for VM to boot in test_net_hotplug
Use the notification mechanism now that the VM has it's primary network
attached.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-21 23:41:37 +00:00
Rob Bradford
1b4b4fb0c2 tests: Validate secondary network connection in test_net_hotplug
Test that additional network interface by SSHing in using that secondary
IP.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-21 23:41:37 +00:00
Rob Bradford
3ed44c41a6 tests: Use a secondary network interface for test_net_hotplug
This gives a reliable way of identifying if the VM has booted as well as
a reliable way to validate the addition of the network interface.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-21 23:41:37 +00:00
Rob Bradford
11eabaf97d tests: Add second network interface definition to guest
Add a second L1 network interface definition to the guest Cloud Init
configuration, including an additional host IP. Do this by splitting the
network range into two /25s. For clarity the network struct members have
also been renamed.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-21 23:41:37 +00:00
dependabot[bot]
4290d4f20e build: Bump the non-rust-vmm group across 2 directories with 25 updates
Bumps the non-rust-vmm group with 20 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [igvm](https://github.com/microsoft/igvm) | ``9b67b6f`` | ``5d2b5a5`` |
| [clap](https://github.com/clap-rs/clap) | `4.5.48` | `4.5.49` |
| [libc](https://github.com/rust-lang/libc) | `0.2.176` | `0.2.177` |
| [gdbstub](https://github.com/daniel5151/gdbstub) | `0.7.7` | `0.7.8` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.40` | `1.2.41` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.5` | `0.7.6` |
| [env_filter](https://github.com/rust-cli/env_logger) | `0.1.3` | `0.1.4` |
| [regex](https://github.com/rust-lang/regex) | `1.11.3` | `1.12.2` |
| [regex-syntax](https://github.com/rust-lang/regex) | `0.8.6` | `0.8.8` |
| [toml_datetime](https://github.com/toml-rs/toml) | `0.7.2` | `0.7.3` |
| [toml_edit](https://github.com/toml-rs/toml) | `0.23.6` | `0.23.7` |
| [windows-targets](https://github.com/microsoft/windows-rs) | `0.53.2` | `0.53.5` |
| [windows_aarch64_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_aarch64_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_gnu](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_gnu](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |

Bumps the non-rust-vmm group with 7 updates in the /fuzz directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.48` | `4.5.49` |
| [libc](https://github.com/rust-lang/libc) | `0.2.176` | `0.2.177` |
| [gdbstub](https://github.com/daniel5151/gdbstub) | `0.7.7` | `0.7.8` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.40` | `1.2.41` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.5` | `0.7.6` |
| [toml_datetime](https://github.com/toml-rs/toml) | `0.7.2` | `0.7.3` |
| [toml_edit](https://github.com/toml-rs/toml) | `0.23.6` | `0.23.7` |



Updates `igvm` from `9b67b6f` to `5d2b5a5`
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](9b67b6fa77...5d2b5a58e0)

Updates `igvm_defs` from `9b67b6f` to `5d2b5a5`
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](9b67b6fa77...5d2b5a58e0)

Updates `clap` from 4.5.48 to 4.5.49
- [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.48...clap_complete-v4.5.49)

Updates `libc` from 0.2.176 to 0.2.177
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.177/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.176...0.2.177)

Updates `gdbstub` from 0.7.7 to 0.7.8
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.7...0.7.8)

Updates `cc` from 1.2.40 to 1.2.41
- [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.2.40...cc-v1.2.41)

Updates `clap_builder` from 4.5.48 to 4.5.49
- [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/v4.5.48...v4.5.49)

Updates `clap_lex` from 0.7.5 to 0.7.6
- [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.5...clap_lex-v0.7.6)

Updates `env_filter` from 0.1.3 to 0.1.4
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/env_filter-v0.1.3...env_filter-v0.1.4)

Updates `find-msvc-tools` from 0.1.3 to 0.1.4
- [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/find-msvc-tools-v0.1.3...find-msvc-tools-v0.1.4)

Updates `regex` from 1.11.3 to 1.12.2
- [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.11.3...1.12.2)

Updates `regex-automata` from 0.4.11 to 0.4.13
- [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.11...regex-automata-0.4.13)

Updates `regex-syntax` from 0.8.6 to 0.8.8
- [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-syntax-0.8.6...regex-syntax-0.8.8)

Updates `toml_datetime` from 0.7.2 to 0.7.3
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.7.2...toml_datetime-v0.7.3)

Updates `toml_edit` from 0.23.6 to 0.23.7
- [Commits](https://github.com/toml-rs/toml/compare/v0.23.6...v0.23.7)

Updates `toml_parser` from 1.0.3 to 1.0.4
- [Commits](https://github.com/toml-rs/toml/compare/toml_parser-v1.0.3...toml_parser-v1.0.4)

Updates `windows-targets` from 0.53.2 to 0.53.5
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnu` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnu` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `clap` from 4.5.48 to 4.5.49
- [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.48...clap_complete-v4.5.49)

Updates `libc` from 0.2.176 to 0.2.177
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.177/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.176...0.2.177)

Updates `gdbstub` from 0.7.7 to 0.7.8
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.7...0.7.8)

Updates `cc` from 1.2.40 to 1.2.41
- [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.2.40...cc-v1.2.41)

Updates `clap_builder` from 4.5.48 to 4.5.49
- [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/v4.5.48...v4.5.49)

Updates `clap_lex` from 0.7.5 to 0.7.6
- [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.5...clap_lex-v0.7.6)

Updates `find-msvc-tools` from 0.1.3 to 0.1.4
- [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/find-msvc-tools-v0.1.3...find-msvc-tools-v0.1.4)

Updates `toml_datetime` from 0.7.2 to 0.7.3
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.7.2...toml_datetime-v0.7.3)

Updates `toml_edit` from 0.23.6 to 0.23.7
- [Commits](https://github.com/toml-rs/toml/compare/v0.23.6...v0.23.7)

Updates `toml_parser` from 1.0.3 to 1.0.4
- [Commits](https://github.com/toml-rs/toml/compare/toml_parser-v1.0.3...toml_parser-v1.0.4)

---
updated-dependencies:
- dependency-name: igvm
  dependency-version: 5d2b5a58e0b294e2adfc923ac4baddfd270eb5a8
  dependency-type: direct:production
  dependency-group: non-rust-vmm
- dependency-name: igvm_defs
  dependency-version: 5d2b5a58e0b294e2adfc923ac4baddfd270eb5a8
  dependency-type: direct:production
  dependency-group: non-rust-vmm
- dependency-name: clap
  dependency-version: 4.5.49
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libc
  dependency-version: 0.2.177
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: gdbstub
  dependency-version: 0.7.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.41
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_builder
  dependency-version: 4.5.49
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_lex
  dependency-version: 0.7.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: env_filter
  dependency-version: 0.1.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: find-msvc-tools
  dependency-version: 0.1.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex
  dependency-version: 1.12.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: regex-automata
  dependency-version: 0.4.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex-syntax
  dependency-version: 0.8.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_datetime
  dependency-version: 0.7.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_edit
  dependency-version: 0.23.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_parser
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.53.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnu
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnu
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap
  dependency-version: 4.5.49
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libc
  dependency-version: 0.2.177
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: gdbstub
  dependency-version: 0.7.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.41
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_builder
  dependency-version: 4.5.49
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_lex
  dependency-version: 0.7.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: find-msvc-tools
  dependency-version: 0.1.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_datetime
  dependency-version: 0.7.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_edit
  dependency-version: 0.23.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_parser
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-21 09:20:56 +00:00
Ruoqing He
a8335d0b06 ci: Extend typos to accept MSIS
Previous RISC-V ACPI related change introduced MSIS which will be
rejected by typo check, let's extend the typos to accept it.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-10-21 07:57:28 +01:00
Can Zhang
d10f6dd357 vmm: Enable RISC-V ACPI support
Add necessary definitions and RISC-V ACPI tables to enable ACPI feature.
More specifically, this commit add MADT definitions for RISC-V AIA
interrupt chips.

Signed-off-by: Can Zhang <icloud9957@gmail.com>
2025-10-18 08:30:18 +00:00
Anirudh Rayabharam
4dcd689cd9 ci: update MSHV workflow & job names
Rename the MSHV CI workflow to better align with the existing naming
scheme and also make the arch explicit.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-17 10:54:41 +00:00
AASTHA RAWAT
68f9e82447 ci: set continue-on-error for mshv infra workflow
Set `continue-on-error` for infra-setup job so that the entire workflow
doesn't fail.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-14 15:00:30 +00:00
AASTHA RAWAT
f256317ac6 ci: add timeout to mshv integration test workflow
Add step-level timeout for running integration tests so that the
workflow doesn't get stuck on any test.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-14 15:00:30 +00:00
Ruoqing He
0a785c1db2 build: Use v0.3.0 of vm-fdt instead of main branch
We are actually using v0.3.0 of vm-fdt since main branch of that crate
already includes everything. Let's pin vm-fdt to v0.3.0 instead.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-10-14 09:05:47 +00:00
Ruoqing He
d3b8300e9c build: Update linux-loader to v0.13.1
Required kernel header are made public in v0.13.1, let's bump to consume
the change.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-10-14 09:05:47 +00:00
AASTHA RAWAT
bb9d3529db ci: update PR trigger for mshv workflow
Pull requests from forked repos cannot access GitHub secrets which
results in failure of MSHV CI. Switching to pull_request_target
resolves this. It allows the workflow to run with access to repo secrets
and ensures that code from the base branch is used instead of forked
code, preventing potential security risks.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-11 08:41:23 +00:00
AASTHA RAWAT
3cf310229c ci: add tag for mshv runner
Use mshv runner for mshv workflows. Disable manual trigger.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-11 08:41:23 +00:00
AASTHA RAWAT
0e50cc320e ci: add mshv integration tests workflow
Add workflow to run integration tests on mshv. It calls the azure
infra setup workflow and executes integration tests in the
provisioned environment.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-11 08:41:23 +00:00
AASTHA RAWAT
9cdcd920b2 ci: add azure infra setup workflow
Add workflow to setup Azure infra to validate MSHV.
This is used to provision the environment before executing tests
on it.

Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
2025-10-11 08:41:23 +00:00
Bo Chen
256f0c39e9 vmm: Drop 'vfio container' when no active vfio devices
This provides clearer life-cycle management of resources around vfio,
and aligns better with the kernel behavior as reported below with vfio
legacy mode (with vfio container/group).

Fixes: #7328

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Yi Wang <foxywang@tencent.com>
2025-10-09 23:59:37 +00:00
Bo Chen
205e62aaa8 scripts: Download jammy images for rate-limiter tests
We recently moved many of our tests to use focal to jammy as the guest
images, including rate-limiter tests (#7367). We forgot to update the
rate-limiter scripts to reflect such change.

Our CI pipeline failed to report such error because our self-host runner
happened to be not working at the time we land the changes (see #7405).

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-10-09 22:49:12 +00:00
Rob Bradford
d760301c8d tests: Reduce parallelism on x86-64 testing
Only use 75% of the available threads - this will reduce dislk and
memory pressure. Reducing the chance of flaky tests.

See: #7405

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-09 11:02:49 +00:00
Muminul Islam
8e40413886 vmm: validate payload correctly when IGVM is provided
While an IGVM is provided validation fails as there is
no kernel or firmware. This patch fixes the sev_snp boot
failure.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-10-09 08:29:07 +01:00
Anirudh Rayabharam
5549d846da vmm: support firmware boot on mshv arm64
MSHV (Microsoft Hypervisor) doesn't expose an ITS to guests. Instead it
exposes a GICv2m MSI Frame for mapping MSIs to SPIs.

Update the MADT generation code to create the GIC MSI Frame structure
instead of the ITS structure whenever the guest vGIC is using a GICv2m
frame. This allows booting guests via firmware on MSHV.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-10-07 21:34:03 +00:00
Philipp Schuster
76bd1418a2 api_client: fix clippy
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-07 16:13:31 +00:00
dependabot[bot]
15db321245 build: Bump the non-rust-vmm group across 2 directories with 20 updates
Bumps the non-rust-vmm group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [serde_with](https://github.com/jonasbb/serde_with) | `3.14.1` | `3.15.0` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.20` | `0.6.21` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.39` | `1.2.40` |
| [lock_api](https://github.com/Amanieu/parking_lot) | `0.4.13` | `0.4.14` |
| [openssl-src](https://github.com/alexcrichton/openssl-src-rs) | `300.5.2+3.5.2` | `300.5.3+3.5.4` |
| [parking_lot](https://github.com/Amanieu/parking_lot) | `0.12.4` | `0.12.5` |
| redox_syscall | `0.5.17` | `0.5.18` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.2.0` | `0.2.1` |

Bumps the non-rust-vmm group with 14 updates in the /fuzz directory:

| Package | From | To |
| --- | --- | --- |
| [serde_with](https://github.com/jonasbb/serde_with) | `3.14.1` | `3.15.0` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.20` | `0.6.21` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.39` | `1.2.40` |
| [lock_api](https://github.com/Amanieu/parking_lot) | `0.4.13` | `0.4.14` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.2.0` | `0.2.1` |
| [windows-targets](https://github.com/microsoft/windows-rs) | `0.53.4` | `0.53.5` |
| [windows_aarch64_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_aarch64_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_gnu](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_i686_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_gnu](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_gnullvm](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |
| [windows_x86_64_msvc](https://github.com/microsoft/windows-rs) | `0.53.0` | `0.53.1` |



Updates `serde_with` from 3.14.1 to 3.15.0
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.1...v3.15.0)

Updates `anstream` from 0.6.20 to 0.6.21
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.20...anstream-v0.6.21)

Updates `cc` from 1.2.39 to 1.2.40
- [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.2.39...cc-v1.2.40)

Updates `find-msvc-tools` from 0.1.2 to 0.1.3
- [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/find-msvc-tools-v0.1.2...find-msvc-tools-v0.1.3)

Updates `lock_api` from 0.4.13 to 0.4.14
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-v0.4.13...lock_api-v0.4.14)

Updates `openssl-src` from 300.5.2+3.5.2 to 300.5.3+3.5.4
- [Release notes](https://github.com/alexcrichton/openssl-src-rs/releases)
- [Commits](https://github.com/alexcrichton/openssl-src-rs/commits)

Updates `parking_lot` from 0.12.4 to 0.12.5
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/parking_lot-v0.12.4...parking_lot-v0.12.5)

Updates `parking_lot_core` from 0.9.11 to 0.9.12
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/parking_lot_core-v0.9.11...parking_lot_core-v0.9.12)

Updates `redox_syscall` from 0.5.17 to 0.5.18

Updates `serde_with_macros` from 3.14.1 to 3.15.0
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.1...v3.15.0)

Updates `windows-link` from 0.2.0 to 0.2.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-targets` from 0.52.6 to 0.53.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnu` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnu` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `serde_with` from 3.14.1 to 3.15.0
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.1...v3.15.0)

Updates `anstream` from 0.6.20 to 0.6.21
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.20...anstream-v0.6.21)

Updates `cc` from 1.2.39 to 1.2.40
- [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.2.39...cc-v1.2.40)

Updates `find-msvc-tools` from 0.1.2 to 0.1.3
- [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/find-msvc-tools-v0.1.2...find-msvc-tools-v0.1.3)

Updates `lock_api` from 0.4.13 to 0.4.14
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-v0.4.13...lock_api-v0.4.14)

Updates `serde_with_macros` from 3.14.1 to 3.15.0
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.1...v3.15.0)

Updates `windows-link` from 0.2.0 to 0.2.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-targets` from 0.53.4 to 0.53.5
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnu` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnu` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnullvm` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_msvc` from 0.53.0 to 0.53.1
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-version: 3.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: anstream
  dependency-version: 0.6.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: find-msvc-tools
  dependency-version: 0.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: lock_api
  dependency-version: 0.4.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: openssl-src
  dependency-version: 300.5.3+3.5.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: parking_lot
  dependency-version: 0.12.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: parking_lot_core
  dependency-version: 0.9.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: redox_syscall
  dependency-version: 0.5.18
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with_macros
  dependency-version: 3.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows-link
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.53.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnu
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnu
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: serde_with
  dependency-version: 3.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: anstream
  dependency-version: 0.6.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: find-msvc-tools
  dependency-version: 0.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: lock_api
  dependency-version: 0.4.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with_macros
  dependency-version: 3.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows-link
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.53.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnu
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnu
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnullvm
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_msvc
  dependency-version: 0.53.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-07 00:50:02 +00:00
dependabot[bot]
15ca4751b7 build: Bump crate-ci/typos from 1.37.1 to 1.38.0
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.37.1 to 1.38.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.37.1...v1.38.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-07 00:18:43 +00:00
Rob Bradford
017a366a6e tests: First pass at replacing focal images with jammy
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-02 07:02:27 +00:00
Rob Bradford
4e008e2dbc tests: Reduce use of focal/jammy variable names
In preparation for removing focal support - start by using a more
generic "disk_config" variable name for the DiskConfig struct vs
embedding the image type.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-02 07:02:27 +00:00
dependabot[bot]
7eb5a6cd70 build: Bump crate-ci/typos from 1.37.0 to 1.37.1
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.37.0 to 1.37.1.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.37.0...v1.37.1)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 00:11:14 +00:00
Rob Bradford
4961b93e69 tests: Fix typo/grammar in live migration tests
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-10-01 08:57:57 +01:00
dependabot[bot]
44f187715f build: Bump crate-ci/typos from 1.36.3 to 1.37.0
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.36.3 to 1.37.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.36.3...v1.37.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:10:44 +00:00
dependabot[bot]
39e540ebb1 build: Bump the non-rust-vmm group across 2 directories with 20 updates
Bumps the non-rust-vmm group with 12 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.226` | `1.0.228` |
| [libc](https://github.com/rust-lang/libc) | `0.2.175` | `0.2.176` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.16` | `2.0.17` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.11` | `1.0.13` |
| [async-channel](https://github.com/smol-rs/async-channel) | `2.3.1` | `2.5.0` |
| [backtrace](https://github.com/rust-lang/backtrace-rs) | `0.3.75` | `0.3.76` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.38` | `1.2.39` |
| [hashbrown](https://github.com/rust-lang/hashbrown) | `0.15.5` | `0.16.0` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.5` | `2.7.6` |
| [quote](https://github.com/dtolnay/quote) | `1.0.40` | `1.0.41` |
| [regex](https://github.com/rust-lang/regex) | `1.11.2` | `1.11.3` |
| [rustix](https://github.com/bytecodealliance/rustix) | `1.0.7` | `1.1.2` |

Bumps the non-rust-vmm group with 8 updates in the /fuzz directory:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.226` | `1.0.228` |
| [libc](https://github.com/rust-lang/libc) | `0.2.175` | `0.2.176` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.16` | `2.0.17` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.11` | `1.0.13` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.38` | `1.2.39` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.5` | `2.7.6` |
| [quote](https://github.com/dtolnay/quote) | `1.0.40` | `1.0.41` |
| [windows-targets](https://github.com/microsoft/windows-rs) | `0.53.3` | `0.53.4` |



Updates `serde` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `libc` from 0.2.175 to 0.2.176
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.176/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.175...0.2.176)

Updates `thiserror` from 2.0.16 to 2.0.17
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.16...2.0.17)

Updates `anstyle` from 1.0.11 to 1.0.13
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.11...v1.0.13)

Updates `async-channel` from 2.3.1 to 2.5.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.3.1...v2.5.0)

Updates `backtrace` from 0.3.75 to 0.3.76
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Changelog](https://github.com/rust-lang/backtrace-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.75...backtrace-v0.3.76)

Updates `cc` from 1.2.38 to 1.2.39
- [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.2.38...cc-v1.2.39)

Updates `gimli` from 0.31.1 to 0.32.3
- [Changelog](https://github.com/gimli-rs/gimli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/gimli/compare/0.31.1...0.32.3)

Updates `hashbrown` from 0.15.5 to 0.16.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.15.5...v0.16.0)

Updates `memchr` from 2.7.5 to 2.7.6
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.5...2.7.6)

Updates `object` from 0.36.7 to 0.37.3
- [Changelog](https://github.com/gimli-rs/object/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/object/compare/0.36.7...0.37.3)

Updates `quote` from 1.0.40 to 1.0.41
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.40...1.0.41)

Updates `regex` from 1.11.2 to 1.11.3
- [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.11.2...1.11.3)

Updates `regex-automata` from 0.4.10 to 0.4.11
- [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/commits)

Updates `rustix` from 1.0.7 to 1.1.2
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGES.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v1.0.7...v1.1.2)

Updates `serde_core` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `serde_derive` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `windows-sys` from 0.59.0 to 0.60.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `serde` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `libc` from 0.2.175 to 0.2.176
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.176/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.175...0.2.176)

Updates `thiserror` from 2.0.16 to 2.0.17
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.16...2.0.17)

Updates `bitfield-struct` from 0.10.1 to 0.11.0
- [Release notes](https://github.com/wrenger/bitfield-struct-rs/releases)
- [Commits](https://github.com/wrenger/bitfield-struct-rs/compare/0.10.1...0.11.0)

Updates `anstyle` from 1.0.11 to 1.0.13
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.11...v1.0.13)

Updates `cc` from 1.2.38 to 1.2.39
- [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.2.38...cc-v1.2.39)

Updates `memchr` from 2.7.5 to 2.7.6
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.5...2.7.6)

Updates `quote` from 1.0.40 to 1.0.41
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.40...1.0.41)

Updates `serde_core` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `serde_derive` from 1.0.226 to 1.0.228
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.226...v1.0.228)

Updates `windows-targets` from 0.53.3 to 0.53.4
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

---
updated-dependencies:
- dependency-name: serde
  dependency-version: 1.0.228
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libc
  dependency-version: 0.2.176
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: thiserror
  dependency-version: 2.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle
  dependency-version: 1.0.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: async-channel
  dependency-version: 2.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: backtrace
  dependency-version: 0.3.76
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.39
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: gimli
  dependency-version: 0.32.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: hashbrown
  dependency-version: 0.16.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.7.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: object
  dependency-version: 0.37.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: quote
  dependency-version: 1.0.41
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex
  dependency-version: 1.11.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex-automata
  dependency-version: 0.4.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustix
  dependency-version: 1.1.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: serde_core
  dependency-version: 1.0.228
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_derive
  dependency-version: 1.0.228
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-sys
  dependency-version: 0.60.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: serde
  dependency-version: 1.0.228
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libc
  dependency-version: 0.2.176
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: thiserror
  dependency-version: 2.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: bitfield-struct
  dependency-version: 0.11.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: anstyle
  dependency-version: 1.0.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.39
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.7.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: quote
  dependency-version: 1.0.41
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_core
  dependency-version: 1.0.228
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_derive
  dependency-version: 1.0.228
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.53.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 03:05:01 +00:00
Philipp Schuster
690741de13 hypervisor: kvm/x86_64: get and set nested guest state
Since the functionality of [0] was backported to
kvm-bindings@v0.12.1 and kvm-ioctls@v0.22.1 [1, 2], we
can now save nested KVM state. This way, nesting works across
state save/resume and live-migration.

[0] https://github.com/rust-vmm/kvm/pull/322
[1] https://github.com/rust-vmm/kvm/pull/349
[2] https://github.com/rust-vmm/kvm/pull/350

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-29 11:44:36 +00:00
Oliver Anderson
4c16285dde vmm: Fix UB in AMX support checks
Rust's aliasing rules do not permit mutating a `usize` through a shared
reference. Unsafe blocks and FFI are no exception.

This PR fixes such a violation detected in the AMX support checks by
passing a raw mutable pointer instead of a shared reference in the
syscall.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP <oliver.anderson@sap.com>
2025-09-26 15:10:21 +00:00
dependabot[bot]
bb713e8c01 build: Bump crate-ci/typos from 1.36.2 to 1.36.3
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.36.2 to 1.36.3.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.36.2...v1.36.3)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-26 07:49:10 +00:00
Philipp Schuster
a6426e3615 devices: gracefully close preserved FDs on device remove
For a graceful resource management of externally provided FDs in Cloud
Hypervisor, corresponding FDs need to be closed on a device removal.
This is the case for virtio-net devices using external FDs, for example.

With the fix introduced in this commit, we allow management software to
properly clean up resources, e.g., libvirt can clean up tap devices.

PS: CHV uses "added" and "removed", which has the same meaning as
hot device attach/hotplug and hot device detach/unplug.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-25 21:25:36 +00:00
Philipp Schuster
f1206a19df block: fix error style
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-25 21:17:06 +00:00
Ruoqing He
f2dfa7f6e0 misc: Use variables directly in format! string
Fix clippy warning `uninlined_format_args` reported by rustc rustc
1.89.0 (29483883e 2025-08-04).

```console
warning: variables can be used directly in the `format!` string
   --> block/src/lib.rs:649:17
    |
649 |                 info!("{} failed to create io_uring instance: {}", error_msg, e);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
    = note: `#[warn(clippy::uninlined_format_args)]` on by default
help: change this to
    |
649 -                 info!("{} failed to create io_uring instance: {}", error_msg, e);
649 +                 info!("{error_msg} failed to create io_uring instance: {e}");
    |
```

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-09-24 02:28:12 +00:00
dependabot[bot]
ea83fe314c build: Bump the non-rust-vmm group across 2 directories with 107 updates
Bumps the non-rust-vmm group with 57 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [zbus](https://github.com/dbus2/zbus) | `5.7.1` | `5.11.0` |
| [serde](https://github.com/serde-rs/serde) | `1.0.208` | `1.0.226` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.143` | `1.0.145` |
| [serde_with](https://github.com/jonasbb/serde_with) | `3.14.0` | `3.14.1` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.99` | `1.0.100` |
| [cfg-if](https://github.com/rust-lang/cfg-if) | `1.0.0` | `1.0.3` |
| [clap](https://github.com/clap-rs/clap) | `4.5.47` | `4.5.48` |
| [log](https://github.com/rust-lang/log) | `0.4.22` | `0.4.28` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.12` | `2.0.16` |
| [zerocopy](https://github.com/google/zerocopy) | `0.8.26` | `0.8.27` |
| [bitfield-struct](https://github.com/wrenger/bitfield-struct-rs) | `0.10.1` | `0.11.0` |
| [num_enum](https://github.com/illicitonion/num_enum) | `0.7.3` | `0.7.4` |
| [blocking](https://github.com/smol-rs/blocking) | `1.6.1` | `1.6.2` |
| [gdbstub](https://github.com/daniel5151/gdbstub) | `0.7.6` | `0.7.7` |
| [micro_http](https://github.com/firecracker-microvm/micro-http) | ``bf50989`` | ``3248cee`` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.19` | `0.6.20` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.2` | `1.1.4` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.6` | `3.0.10` |
| [async-broadcast](https://github.com/smol-rs/async-broadcast) | `0.7.1` | `0.7.2` |
| [async-executor](https://github.com/smol-rs/async-executor) | `1.13.1` | `1.13.3` |
| [async-io](https://github.com/smol-rs/async-io) | `2.5.0` | `2.6.0` |
| [async-lock](https://github.com/smol-rs/async-lock) | `3.4.0` | `3.4.1` |
| [async-signal](https://github.com/smol-rs/async-signal) | `0.2.12` | `0.2.13` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.16.0` | `3.19.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.34` | `1.2.38` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.4` | `0.7.5` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.3` | `1.0.4` |
| [crc32fast](https://github.com/srijs/rust-crc32fast) | `1.4.2` | `1.5.0` |
| [env_filter](https://github.com/rust-cli/env_logger) | `0.1.2` | `0.1.3` |
| [errno](https://github.com/lambda-fairy/rust-errno) | `0.3.13` | `0.3.14` |
| [event-listener-strategy](https://github.com/smol-rs/event-listener-strategy) | `0.5.3` | `0.5.4` |
| [futures-lite](https://github.com/smol-rs/futures-lite) | `2.6.0` | `2.6.1` |
| [glob](https://github.com/rust-lang/glob) | `0.3.2` | `0.3.3` |
| [hashbrown](https://github.com/rust-lang/hashbrown) | `0.15.4` | `0.15.5` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.8.0` | `2.11.4` |
| libredox | `0.1.3` | `0.1.10` |
| [libz-sys](https://github.com/rust-lang/libz-sys) | `1.1.18` | `1.1.22` |
| [lock_api](https://github.com/Amanieu/parking_lot) | `0.4.12` | `0.4.13` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.2` | `2.7.5` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.2` | `1.21.3` |
| [openssl-src](https://github.com/alexcrichton/openssl-src-rs) | `300.3.2+3.3.2` | `300.5.2+3.5.2` |
| [openssl-sys](https://github.com/sfackler/rust-openssl) | `0.9.104` | `0.9.109` |
| [parking_lot](https://github.com/Amanieu/parking_lot) | `0.12.1` | `0.12.4` |
| [pin-project-lite](https://github.com/taiki-e/pin-project-lite) | `0.2.15` | `0.2.16` |
| [pkg-config](https://github.com/rust-lang/pkg-config-rs) | `0.3.31` | `0.3.32` |
| [polling](https://github.com/smol-rs/polling) | `3.6.0` | `3.11.0` |
| [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) | `0.2.20` | `0.2.21` |
| [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) | `3.3.0` | `3.4.0` |
| [regex](https://github.com/rust-lang/regex) | `1.11.1` | `1.11.2` |
| [regex-automata](https://github.com/rust-lang/regex) | `0.4.9` | `0.4.10` |
| [regex-syntax](https://github.com/rust-lang/regex) | `0.8.5` | `0.8.6` |
| [serde_repr](https://github.com/dtolnay/serde-repr) | `0.1.19` | `0.1.20` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.12.0` | `3.23.0` |
| [tracing](https://github.com/tokio-rs/tracing) | `0.1.40` | `0.1.41` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.18` | `1.0.19` |
| [wasi](https://github.com/bytecodealliance/wasi-rs) | `0.11.0+wasi-snapshot-preview1` | `0.11.1+wasi-snapshot-preview1` |
| [zvariant_utils](https://github.com/dbus2/zbus) | `3.2.0` | `3.2.1` |

Bumps the non-rust-vmm group with 44 updates in the /fuzz directory:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.208` | `1.0.226` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.143` | `1.0.145` |
| [serde_with](https://github.com/jonasbb/serde_with) | `3.14.0` | `3.14.1` |
| [cfg-if](https://github.com/rust-lang/cfg-if) | `1.0.0` | `1.0.3` |
| [clap](https://github.com/clap-rs/clap) | `4.5.47` | `4.5.48` |
| [log](https://github.com/rust-lang/log) | `0.4.22` | `0.4.28` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.12` | `2.0.16` |
| [zerocopy](https://github.com/google/zerocopy) | `0.8.26` | `0.8.27` |
| [num_enum](https://github.com/illicitonion/num_enum) | `0.7.2` | `0.7.4` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.2.15` | `0.2.16` |
| [gdbstub](https://github.com/daniel5151/gdbstub) | `0.7.6` | `0.7.7` |
| [micro_http](https://github.com/firecracker-microvm/micro-http) | ``bf50989`` | ``3248cee`` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.15` | `0.6.20` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.8` | `1.0.11` |
| [anstyle-parse](https://github.com/rust-cli/anstyle) | `0.2.5` | `0.2.7` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.1` | `1.1.4` |
| [autocfg](https://github.com/cuviper/autocfg) | `1.3.0` | `1.5.0` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.16.0` | `3.19.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.11` | `1.2.38` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.2` | `1.0.4` |
| [enumflags2](https://github.com/meithecatte/enumflags2) | `0.7.10` | `0.7.12` |
| [equivalent](https://github.com/indexmap-rs/equivalent) | `1.0.1` | `1.0.2` |
| [futures-core](https://github.com/rust-lang/futures-rs) | `0.3.30` | `0.3.31` |
| [futures-sink](https://github.com/rust-lang/futures-rs) | `0.3.30` | `0.3.31` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.5.0` | `2.11.4` |
| [itoa](https://github.com/dtolnay/itoa) | `1.0.11` | `1.0.15` |
| [lock_api](https://github.com/Amanieu/parking_lot) | `0.4.12` | `0.4.13` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.4` | `2.7.5` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.2` | `1.21.3` |
| [ppv-lite86](https://github.com/cryptocorrosion/cryptocorrosion) | `0.2.20` | `0.2.21` |
| [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) | `3.2.0` | `3.4.0` |
| [proc-macro2](https://github.com/dtolnay/proc-macro2) | `1.0.92` | `1.0.101` |
| [quote](https://github.com/dtolnay/quote) | `1.0.37` | `1.0.40` |
| [r-efi](https://github.com/r-efi/r-efi) | `5.2.0` | `5.3.0` |
| [rand](https://github.com/rust-random/rand) | `0.9.0` | `0.9.2` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.21` | `1.0.22` |
| [ryu](https://github.com/dtolnay/ryu) | `1.0.18` | `1.0.20` |
| [signal-hook-registry](https://github.com/vorner/signal-hook) | `1.4.2` | `1.4.6` |
| [syn](https://github.com/dtolnay/syn) | `2.0.95` | `2.0.106` |
| [unicode-ident](https://github.com/dtolnay/unicode-ident) | `1.0.13` | `1.0.19` |
| [wasi](https://github.com/bytecodealliance/wasi-rs) | `0.11.0+wasi-snapshot-preview1` | `0.11.1+wasi-snapshot-preview1` |
| [arbitrary](https://github.com/rust-fuzz/arbitrary) | `1.4.1` | `1.4.2` |
| [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) | `0.4.7` | `0.4.10` |
| [jobserver](https://github.com/rust-lang/jobserver-rs) | `0.1.32` | `0.1.34` |



Updates `zbus` from 5.7.1 to 5.11.0
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-5.7.1...zbus-5.11.0)

Updates `serde` from 1.0.208 to 1.0.226
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.226)

Updates `serde_json` from 1.0.143 to 1.0.145
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.143...v1.0.145)

Updates `serde_with` from 3.14.0 to 3.14.1
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.0...v3.14.1)

Updates `anyhow` from 1.0.99 to 1.0.100
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.99...1.0.100)

Updates `cfg-if` from 1.0.0 to 1.0.3
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/1.0.0...v1.0.3)

Updates `clap` from 4.5.47 to 4.5.48
- [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.47...clap_complete-v4.5.48)

Updates `log` from 0.4.22 to 0.4.28
- [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.22...0.4.28)

Updates `thiserror` from 2.0.12 to 2.0.16
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.12...2.0.16)

Updates `zerocopy` from 0.8.26 to 0.8.27
- [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.8.26...v0.8.27)

Updates `bitfield-struct` from 0.10.1 to 0.11.0
- [Release notes](https://github.com/wrenger/bitfield-struct-rs/releases)
- [Commits](https://github.com/wrenger/bitfield-struct-rs/compare/0.10.1...0.11.0)

Updates `num_enum` from 0.7.3 to 0.7.4
- [Commits](https://github.com/illicitonion/num_enum/compare/0.7.3...0.7.4)

Updates `blocking` from 1.6.1 to 1.6.2
- [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.6.1...v1.6.2)

Updates `gdbstub` from 0.7.6 to 0.7.7
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.6...0.7.7)

Updates `micro_http` from `bf50989` to `3248cee`
- [Commits](bf50989160...3248ceeae4)

Updates `anstream` from 0.6.19 to 0.6.20
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.19...anstream-v0.6.20)

Updates `anstyle-query` from 1.1.2 to 1.1.4
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.4)

Updates `anstyle-wincon` from 3.0.6 to 3.0.10
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.6...anstyle-wincon-v3.0.10)

Updates `async-broadcast` from 0.7.1 to 0.7.2
- [Release notes](https://github.com/smol-rs/async-broadcast/releases)
- [Changelog](https://github.com/smol-rs/async-broadcast/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-broadcast/compare/0.7.1...0.7.2)

Updates `async-executor` from 1.13.1 to 1.13.3
- [Release notes](https://github.com/smol-rs/async-executor/releases)
- [Changelog](https://github.com/smol-rs/async-executor/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-executor/compare/v1.13.1...v1.13.3)

Updates `async-io` from 2.5.0 to 2.6.0
- [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.5.0...v2.6.0)

Updates `async-lock` from 3.4.0 to 3.4.1
- [Release notes](https://github.com/smol-rs/async-lock/releases)
- [Changelog](https://github.com/smol-rs/async-lock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-lock/compare/v3.4.0...v3.4.1)

Updates `async-signal` from 0.2.12 to 0.2.13
- [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.12...v0.2.13)

Updates `bumpalo` from 3.16.0 to 3.19.0
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/commits)

Updates `cc` from 1.2.34 to 1.2.38
- [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.2.34...cc-v1.2.38)

Updates `clap_builder` from 4.5.47 to 4.5.48
- [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/v4.5.47...v4.5.48)

Updates `clap_lex` from 0.7.4 to 0.7.5
- [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.4...clap_lex-v0.7.5)

Updates `colorchoice` from 1.0.3 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `crc32fast` from 1.4.2 to 1.5.0
- [Commits](https://github.com/srijs/rust-crc32fast/compare/v1.4.2...v1.5.0)

Updates `darling` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `darling_core` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `darling_macro` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `env_filter` from 0.1.2 to 0.1.3
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/env_filter-v0.1.2...env_filter-v0.1.3)

Updates `errno` from 0.3.13 to 0.3.14
- [Release notes](https://github.com/lambda-fairy/rust-errno/releases)
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/commits)

Updates `event-listener-strategy` from 0.5.3 to 0.5.4
- [Release notes](https://github.com/smol-rs/event-listener-strategy/releases)
- [Changelog](https://github.com/smol-rs/event-listener-strategy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/event-listener-strategy/compare/v0.5.3...v0.5.4)

Updates `futures-lite` from 2.6.0 to 2.6.1
- [Release notes](https://github.com/smol-rs/futures-lite/releases)
- [Changelog](https://github.com/smol-rs/futures-lite/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/futures-lite/compare/v2.6.0...v2.6.1)

Updates `glob` from 0.3.2 to 0.3.3
- [Release notes](https://github.com/rust-lang/glob/releases)
- [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/glob/compare/v0.3.2...v0.3.3)

Updates `hashbrown` from 0.15.4 to 0.15.5
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.15.4...v0.15.5)

Updates `indexmap` from 2.8.0 to 2.11.4
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.8.0...2.11.4)

Updates `libredox` from 0.1.3 to 0.1.10

Updates `libz-sys` from 1.1.18 to 1.1.22
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/compare/1.1.18...1.1.22)

Updates `lock_api` from 0.4.12 to 0.4.13
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.12...lock_api-v0.4.13)

Updates `memchr` from 2.7.2 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.2...2.7.5)

Updates `num_enum_derive` from 0.7.3 to 0.7.4
- [Commits](https://github.com/illicitonion/num_enum/compare/0.7.3...0.7.4)

Updates `once_cell` from 1.20.2 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.21.3)

Updates `openssl-src` from 300.3.2+3.3.2 to 300.5.2+3.5.2
- [Release notes](https://github.com/alexcrichton/openssl-src-rs/releases)
- [Commits](https://github.com/alexcrichton/openssl-src-rs/commits)

Updates `openssl-sys` from 0.9.104 to 0.9.109
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.104...openssl-sys-v0.9.109)

Updates `parking_lot` from 0.12.1 to 0.12.4
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.1...parking_lot-v0.12.4)

Updates `parking_lot_core` from 0.9.9 to 0.9.11
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/core-0.9.9...parking_lot_core-v0.9.11)

Updates `pin-project-lite` from 0.2.15 to 0.2.16
- [Release notes](https://github.com/taiki-e/pin-project-lite/releases)
- [Changelog](https://github.com/taiki-e/pin-project-lite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project-lite/compare/v0.2.15...v0.2.16)

Updates `pkg-config` from 0.3.31 to 0.3.32
- [Changelog](https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/pkg-config-rs/compare/0.3.31...0.3.32)

Updates `polling` from 3.6.0 to 3.11.0
- [Release notes](https://github.com/smol-rs/polling/releases)
- [Changelog](https://github.com/smol-rs/polling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/polling/compare/v3.6.0...v3.11.0)

Updates `ppv-lite86` from 0.2.20 to 0.2.21
- [Commits](https://github.com/cryptocorrosion/cryptocorrosion/commits/ppv-lite86-0.2.21)

Updates `proc-macro-crate` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/bkchr/proc-macro-crate/releases)
- [Commits](https://github.com/bkchr/proc-macro-crate/compare/v3.3.0...v3.4.0)

Updates `redox_syscall` from 0.4.1 to 0.5.17

Updates `regex` from 1.11.1 to 1.11.2
- [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.11.1...1.11.2)

Updates `regex-automata` from 0.4.9 to 0.4.10
- [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.9...regex-automata-0.4.10)

Updates `regex-syntax` from 0.8.5 to 0.8.6
- [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-syntax-0.8.5...regex-syntax-0.8.6)

Updates `serde_derive` from 1.0.208 to 1.0.226
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.226)

Updates `serde_repr` from 0.1.19 to 0.1.20
- [Release notes](https://github.com/dtolnay/serde-repr/releases)
- [Commits](https://github.com/dtolnay/serde-repr/compare/0.1.19...0.1.20)

Updates `serde_with_macros` from 3.14.0 to 3.14.1
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.0...v3.14.1)

Updates `tempfile` from 3.12.0 to 3.23.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.12.0...v3.23.0)

Updates `toml_datetime` from 0.6.11 to 0.7.2
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.6.11...toml_datetime-v0.7.2)

Updates `toml_edit` from 0.22.24 to 0.23.6
- [Commits](https://github.com/toml-rs/toml/compare/v0.22.24...v0.23.6)

Updates `tracing` from 0.1.40 to 0.1.41
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.40...tracing-0.1.41)

Updates `tracing-attributes` from 0.1.27 to 0.1.30
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-attributes-0.1.27...tracing-attributes-0.1.30)

Updates `tracing-core` from 0.1.32 to 0.1.34
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-core-0.1.32...tracing-core-0.1.34)

Updates `unicode-ident` from 1.0.18 to 1.0.19
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.18...1.0.19)

Updates `wasi` from 0.11.0+wasi-snapshot-preview1 to 0.11.1+wasi-snapshot-preview1
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.11.0...0.11.1)

Updates `windows-sys` from 0.52.0 to 0.59.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.59.0)

Updates `windows-targets` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_gnullvm` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_msvc` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnu` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_msvc` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnu` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnullvm` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_msvc` from 0.48.5 to 0.52.6
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `winnow` from 0.7.2 to 0.7.13
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v0.7.2...v0.7.13)

Updates `zbus_macros` from 5.7.1 to 5.11.0
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zbus-5.7.1...zbus-5.11.0)

Updates `zerocopy-derive` from 0.7.35 to 0.8.27
- [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.35...v0.8.27)

Updates `zvariant_utils` from 3.2.0 to 3.2.1
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zvariant_utils-3.2.0...zvariant-3.2.1)

Updates `serde` from 1.0.208 to 1.0.226
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.226)

Updates `serde_json` from 1.0.143 to 1.0.145
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.143...v1.0.145)

Updates `serde_with` from 3.14.0 to 3.14.1
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.0...v3.14.1)

Updates `anyhow` from 1.0.98 to 1.0.100
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.99...1.0.100)

Updates `cfg-if` from 1.0.0 to 1.0.3
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/1.0.0...v1.0.3)

Updates `clap` from 4.5.47 to 4.5.48
- [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.47...clap_complete-v4.5.48)

Updates `epoll` from 4.3.3 to 4.4.0
- [Release notes](https://github.com/nathansizemore/epoll/releases)
- [Commits](https://github.com/nathansizemore/epoll/compare/4.3.3...4.4.0)

Updates `libc` from 0.2.169 to 0.2.175
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.175/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.169...0.2.175)

Updates `log` from 0.4.22 to 0.4.28
- [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.22...0.4.28)

Updates `thiserror` from 2.0.12 to 2.0.16
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.12...2.0.16)

Updates `zerocopy` from 0.8.26 to 0.8.27
- [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.8.26...v0.8.27)

Updates `num_enum` from 0.7.2 to 0.7.4
- [Commits](https://github.com/illicitonion/num_enum/compare/0.7.3...0.7.4)

Updates `getrandom` from 0.2.15 to 0.2.16
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.15...v0.2.16)

Updates `gdbstub` from 0.7.6 to 0.7.7
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.6...0.7.7)

Updates `landlock` from 0.4.2 to 0.4.3
- [Release notes](https://github.com/landlock-lsm/rust-landlock/releases)
- [Changelog](https://github.com/landlock-lsm/rust-landlock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/landlock-lsm/rust-landlock/compare/v0.4.2...v0.4.3)

Updates `micro_http` from `bf50989` to `3248cee`
- [Commits](bf50989160...3248ceeae4)

Updates `anstream` from 0.6.15 to 0.6.20
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.19...anstream-v0.6.20)

Updates `anstyle` from 1.0.8 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.8...v1.0.11)

Updates `anstyle-parse` from 0.2.5 to 0.2.7
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.5...anstyle-parse-v0.2.7)

Updates `anstyle-query` from 1.1.1 to 1.1.4
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.4)

Updates `anstyle-wincon` from 3.0.4 to 3.0.10
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.6...anstyle-wincon-v3.0.10)

Updates `autocfg` from 1.3.0 to 1.5.0
- [Commits](https://github.com/cuviper/autocfg/compare/1.3.0...1.5.0)

Updates `bumpalo` from 3.16.0 to 3.19.0
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/commits)

Updates `cc` from 1.1.11 to 1.2.38
- [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.2.34...cc-v1.2.38)

Updates `clap_builder` from 4.5.47 to 4.5.48
- [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/v4.5.47...v4.5.48)

Updates `colorchoice` from 1.0.2 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `darling` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `darling_core` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `darling_macro` from 0.20.10 to 0.21.3
- [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.10...v0.21.3)

Updates `enumflags2` from 0.7.10 to 0.7.12
- [Release notes](https://github.com/meithecatte/enumflags2/releases)
- [Commits](https://github.com/meithecatte/enumflags2/compare/v0.7.10...v0.7.12)

Updates `enumflags2_derive` from 0.7.10 to 0.7.12
- [Release notes](https://github.com/meithecatte/enumflags2/releases)
- [Commits](https://github.com/meithecatte/enumflags2/compare/v0.7.10...v0.7.12)

Updates `equivalent` from 1.0.1 to 1.0.2
- [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2)

Updates `futures-core` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `futures-sink` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `indexmap` from 2.5.0 to 2.11.4
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.8.0...2.11.4)

Updates `itoa` from 1.0.11 to 1.0.15
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.11...1.0.15)

Updates `lock_api` from 0.4.12 to 0.4.13
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.12...lock_api-v0.4.13)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.2...2.7.5)

Updates `num_enum_derive` from 0.7.2 to 0.7.4
- [Commits](https://github.com/illicitonion/num_enum/compare/0.7.3...0.7.4)

Updates `once_cell` from 1.20.2 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.21.3)

Updates `ppv-lite86` from 0.2.20 to 0.2.21
- [Commits](https://github.com/cryptocorrosion/cryptocorrosion/commits/ppv-lite86-0.2.21)

Updates `proc-macro-crate` from 3.2.0 to 3.4.0
- [Release notes](https://github.com/bkchr/proc-macro-crate/releases)
- [Commits](https://github.com/bkchr/proc-macro-crate/compare/v3.3.0...v3.4.0)

Updates `proc-macro2` from 1.0.92 to 1.0.101
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.92...1.0.101)

Updates `quote` from 1.0.37 to 1.0.40
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.40)

Updates `r-efi` from 5.2.0 to 5.3.0
- [Release notes](https://github.com/r-efi/r-efi/releases)
- [Changelog](https://github.com/r-efi/r-efi/blob/main/NEWS.md)
- [Commits](https://github.com/r-efi/r-efi/compare/v5.2.0...v5.3.0)

Updates `rand` from 0.9.0 to 0.9.2
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.9.0...rand_core-0.9.2)

Updates `rustversion` from 1.0.21 to 1.0.22
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.21...1.0.22)

Updates `ryu` from 1.0.18 to 1.0.20
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.20)

Updates `serde_derive` from 1.0.208 to 1.0.226
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.226)

Updates `serde_with_macros` from 3.14.0 to 3.14.1
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.14.0...v3.14.1)

Updates `signal-hook-registry` from 1.4.2 to 1.4.6
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.2...registry-v1.4.6)

Updates `syn` from 2.0.95 to 2.0.106
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.95...2.0.106)

Updates `toml_datetime` from 0.6.8 to 0.7.2
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.6.11...toml_datetime-v0.7.2)

Updates `toml_edit` from 0.22.22 to 0.23.6
- [Commits](https://github.com/toml-rs/toml/compare/v0.22.24...v0.23.6)

Updates `unicode-ident` from 1.0.13 to 1.0.19
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.18...1.0.19)

Updates `wasi` from 0.11.0+wasi-snapshot-preview1 to 0.11.1+wasi-snapshot-preview1
- [Commits](https://github.com/bytecodealliance/wasi-rs/compare/0.11.0...0.11.1)

Updates `windows-sys` from 0.52.0 to 0.60.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.59.0)

Updates `windows-targets` from 0.52.6 to 0.53.3
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_aarch64_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnu` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_i686_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits/0.53.0)

Updates `windows_i686_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnu` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_gnullvm` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows_x86_64_msvc` from 0.52.6 to 0.53.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `winnow` from 0.6.19 to 0.7.13
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v0.7.2...v0.7.13)

Updates `zerocopy-derive` from 0.7.35 to 0.8.27
- [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.35...v0.8.27)

Updates `arbitrary` from 1.4.1 to 1.4.2
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/compare/v1.4.1...v1.4.2)

Updates `libfuzzer-sys` from 0.4.7 to 0.4.10
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.7...0.4.10)

Updates `jobserver` from 0.1.32 to 0.1.34
- [Commits](https://github.com/rust-lang/jobserver-rs/compare/0.1.32...0.1.34)

---
updated-dependencies:
- dependency-name: zbus
  dependency-version: 5.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: serde
  dependency-version: 1.0.226
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_json
  dependency-version: 1.0.145
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with
  dependency-version: 3.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anyhow
  dependency-version: 1.0.100
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cfg-if
  dependency-version: 1.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap
  dependency-version: 4.5.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: log
  dependency-version: 0.4.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: thiserror
  dependency-version: 2.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zerocopy
  dependency-version: 0.8.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: bitfield-struct
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: num_enum
  dependency-version: 0.7.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: blocking
  dependency-version: 1.6.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: gdbstub
  dependency-version: 0.7.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: micro_http
  dependency-version: 3248ceeae41461d034624b582d5d358cd6e6f89f
  dependency-type: direct:production
  dependency-group: non-rust-vmm
- dependency-name: anstream
  dependency-version: 0.6.20
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle-query
  dependency-version: 1.1.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle-wincon
  dependency-version: 3.0.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: async-broadcast
  dependency-version: 0.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: async-executor
  dependency-version: 1.13.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: async-io
  dependency-version: 2.6.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: async-lock
  dependency-version: 3.4.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: async-signal
  dependency-version: 0.2.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: bumpalo
  dependency-version: 3.19.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_builder
  dependency-version: 4.5.48
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap_lex
  dependency-version: 0.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: crc32fast
  dependency-version: 1.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: darling
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: darling_core
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: darling_macro
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: env_filter
  dependency-version: 0.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: errno
  dependency-version: 0.3.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: event-listener-strategy
  dependency-version: 0.5.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: futures-lite
  dependency-version: 2.6.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: glob
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: hashbrown
  dependency-version: 0.15.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: indexmap
  dependency-version: 2.11.4
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: libredox
  dependency-version: 0.1.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libz-sys
  dependency-version: 1.1.22
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: lock_api
  dependency-version: 0.4.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: num_enum_derive
  dependency-version: 0.7.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: once_cell
  dependency-version: 1.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: openssl-src
  dependency-version: 300.5.2+3.5.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: openssl-sys
  dependency-version: 0.9.109
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: parking_lot
  dependency-version: 0.12.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: parking_lot_core
  dependency-version: 0.9.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: pin-project-lite
  dependency-version: 0.2.16
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: pkg-config
  dependency-version: 0.3.32
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: polling
  dependency-version: 3.11.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: ppv-lite86
  dependency-version: 0.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: proc-macro-crate
  dependency-version: 3.4.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: redox_syscall
  dependency-version: 0.5.17
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: regex
  dependency-version: 1.11.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex-automata
  dependency-version: 0.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex-syntax
  dependency-version: 0.8.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_derive
  dependency-version: 1.0.226
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_repr
  dependency-version: 0.1.20
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with_macros
  dependency-version: 3.14.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: tempfile
  dependency-version: 3.23.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: toml_datetime
  dependency-version: 0.7.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: toml_edit
  dependency-version: 0.23.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: tracing
  dependency-version: 0.1.41
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: tracing-attributes
  dependency-version: 0.1.30
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: tracing-core
  dependency-version: 0.1.34
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: unicode-ident
  dependency-version: 1.0.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: wasi
  dependency-version: 0.11.1+wasi-snapshot-preview1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-sys
  dependency-version: 0.59.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_gnullvm
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_msvc
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnu
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_msvc
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnu
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnullvm
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_msvc
  dependency-version: 0.52.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: winnow
  dependency-version: 0.7.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zbus_macros
  dependency-version: 5.11.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zerocopy-derive
  dependency-version: 0.8.27
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zvariant_utils
  dependency-version: 3.2.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde
  dependency-version: 1.0.226
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_json
  dependency-version: 1.0.145
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with
  dependency-version: 3.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anyhow
  dependency-version: 1.0.100
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: cfg-if
  dependency-version: 1.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: clap
  dependency-version: 4.5.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: epoll
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: libc
  dependency-version: 0.2.175
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: log
  dependency-version: 0.4.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: thiserror
  dependency-version: 2.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zerocopy
  dependency-version: 0.8.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: num_enum
  dependency-version: 0.7.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: getrandom
  dependency-version: 0.2.16
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: gdbstub
  dependency-version: 0.7.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: landlock
  dependency-version: 0.4.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: micro_http
  dependency-version: 3248ceeae41461d034624b582d5d358cd6e6f89f
  dependency-type: direct:production
  dependency-group: non-rust-vmm
- dependency-name: anstream
  dependency-version: 0.6.20
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle-parse
  dependency-version: 0.2.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle-query
  dependency-version: 1.1.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: anstyle-wincon
  dependency-version: 3.0.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: autocfg
  dependency-version: 1.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: bumpalo
  dependency-version: 3.19.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.38
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: clap_builder
  dependency-version: 4.5.48
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: darling
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: darling_core
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: darling_macro
  dependency-version: 0.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: enumflags2
  dependency-version: 0.7.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: enumflags2_derive
  dependency-version: 0.7.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: equivalent
  dependency-version: 1.0.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: futures-core
  dependency-version: 0.3.31
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: futures-sink
  dependency-version: 0.3.31
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: indexmap
  dependency-version: 2.11.4
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: itoa
  dependency-version: 1.0.15
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: lock_api
  dependency-version: 0.4.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: num_enum_derive
  dependency-version: 0.7.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: once_cell
  dependency-version: 1.21.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: ppv-lite86
  dependency-version: 0.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: proc-macro-crate
  dependency-version: 3.4.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: proc-macro2
  dependency-version: 1.0.101
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: quote
  dependency-version: 1.0.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: r-efi
  dependency-version: 5.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: rand
  dependency-version: 0.9.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustversion
  dependency-version: 1.0.22
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: ryu
  dependency-version: 1.0.20
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_derive
  dependency-version: 1.0.226
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: serde_with_macros
  dependency-version: 3.14.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: signal-hook-registry
  dependency-version: 1.4.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: syn
  dependency-version: 2.0.106
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: toml_datetime
  dependency-version: 0.7.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: toml_edit
  dependency-version: 0.23.6
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: unicode-ident
  dependency-version: 1.0.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: wasi
  dependency-version: 0.11.1+wasi-snapshot-preview1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: windows-sys
  dependency-version: 0.60.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows-targets
  dependency-version: 0.53.3
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_aarch64_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnu
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_i686_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnu
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_gnullvm
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: windows_x86_64_msvc
  dependency-version: 0.53.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: winnow
  dependency-version: 0.7.13
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zerocopy-derive
  dependency-version: 0.8.27
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: arbitrary
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: libfuzzer-sys
  dependency-version: 0.4.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: jobserver
  dependency-version: 0.1.34
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-24 02:28:12 +00:00
Ruoqing He
ad0f695352 ci: Make package-ecosystem combination unique
"Update configs must have a unique combination of 'package-ecosystem',
'directory', and 'target-branch'. Ecosystem 'cargo' has overlapping
directories for target branch 'main'."

Drop `target-branch` in rust-vmm group to make those two unique.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-09-23 11:08:31 +01:00
dependabot[bot]
70c798d2b9 build: Bump landlock from 0.4.2 to 0.4.3
Bumps [landlock](https://github.com/landlock-lsm/rust-landlock) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/landlock-lsm/rust-landlock/releases)
- [Changelog](https://github.com/landlock-lsm/rust-landlock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/landlock-lsm/rust-landlock/compare/v0.4.2...v0.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 23:50:49 +00:00
Ruoqing He
db37ef2ad7 ci: Group dependabot updates to reduce noise
Use a workaround [1] to group rust-vmm and non-rust-vmm updates raised
by dependabot, which reduces noise from dependabot.

[1] https://github.com/dependabot/dependabot-core/issues/1778#issuecomment-1988140219

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-09-22 22:27:44 +01:00
Philipp Schuster
452424b66e vmm: api: abstract FD handling behind functions
## TL;DR

This unifies error handling, implementation, and logging of config
objects that are populated with additional FDs received as part of
the HTTP API request from the management software. This prevents current
and future code in repetition.

In the future, if we want to support let's say virtio-blk with external
FDs, the AddBlk API handler simply needs a call to `attach_fds_to_cfg()`
and gets all the magic for free.

## Motivation

The motivation of the new abstraction is to provide a verbose, solid,
and bulletproof solution for a complex domain. The interaction between

- the management layer,
- the passing of file descriptors over UNIX domain sockets via
  SCM_RIGHTS,
- the attachment of configurations to those FDs,
- and the ability to give new developers clear insights into what
  happens under the hood

is not trivial. These factors justify encapsulating the complexity
behind a convenient and well-documented abstraction, making the system
both robust in production and approachable for new developers.

In addition, it allows us to perform unit testing. Further, We get rid
of existing partial code duplication and inconsistencies.

Finally, while this approach may initially result in more code, every
new handler that accepts FDs benefits from reduced duplication and a
correct implementation by relying on the shared abstraction. This will
also enable future functionality, such as virtio-blk devices backed by
FDs which can then be integrated with ease.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:29:54 +00:00
Philipp Schuster
ed27e93b81 vmm: remove special serialization of network FDs
Deserializing values as `-1` makes sense to prevent errors, so let's
keep it. However, serializing them differently adds confusion. For
example, a `ch-remote info` call should not report `-1` but the actual
FDs.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:29:54 +00:00
Philipp Schuster
0cd87053ee vmm: document + FD (de)serialization + warn -> debug
(1) The old messages are missing the "why" part. With this change, users
    of Cloud Hypervisor have somehow more context and people looking at
    the code perfectly know what's going on.

(2) Using warn! implies that the user should take action, but in this
    case, there’s nothing the user can do. If the API is used correctly
    and file descriptors are passed via an SCM_RIGHTS message over a
    UNIX domain socket, everything works as intended. In that case,
    there's no need to issue a warning — debug! is sufficient.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:29:54 +00:00
Philipp Schuster
60efa1aa03 vmm: doc improvement for "magic" network FD handling
Live migration, state save/resume, and hotplug are not trivial when it
comes to virtio-net devices backed by externally provided FDs. As the
mechanism behind it can be considered as quite "multi-step magic" even
for experienced programmers, it makes sense to thoroughly document this
to ease debugging and to improve the mental model of developers working
on this in the future.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:29:54 +00:00
Philipp Schuster
fae32412dc vmm: logger: improve code, remove duplication
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:28:35 +00:00
Philipp Schuster
7a5781e5a2 vmm: logger: improve output of timestamp
Streamline the output format of the timestamp of a message.
The old format doesn't nicely align across multiple lines.

# Example (old style)
```
cloud-hypervisor: 858.465660ms: <vcpu0> DEBUG:devices/src/ioapic.rs:154 -- IOAPIC_R @ offset 0x10
cloud-hypervisor: 858.507342ms: <vcpu0> DEBUG:devices/src/ioapic.rs:298 -- IOAPIC_R reg 0x1
cloud-hypervisor: 1.010001s: <vcpu0> DEBUG:devices/src/ioapic.rs:174 -- IOAPIC_W @ offset 0x0
cloud-hypervisor: 1.010067s: <vcpu0> DEBUG:devices/src/ioapic.rs:154 -- IOAPIC_R @ offset 0x10
```

# Example (new style)
```
cloud-hypervisor:   0.731399s: <vcpu0> DEBUG:devices/src/ioapic.rs:174 -- IOAPIC_W @ offset 0x10
cloud-hypervisor:   0.731420s: <vcpu0> DEBUG:devices/src/ioapic.rs:252 -- IOAPIC_W reg 0x2a, val 0x10000
cloud-hypervisor:  17.026073s: <vmm> INFO:vmm/src/api/mod.rs:898 -- API request event: VmInfo
cloud-hypervisor:  17.263210s: <vmm> INFO:vmm/src/api/mod.rs:898 -- API request event: VmInfo
cloud-hypervisor:  17.547915s: <vmm> INFO:vmm/src/api/mod.rs:898 -- API request event: VmInfo
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-22 14:28:35 +00:00
dependabot[bot]
e5c9f7d615 build: Bump igvm_defs from dff4ebc to 9b67b6f
Bumps [igvm_defs](https://github.com/microsoft/igvm) from `dff4ebc` to `9b67b6f`.
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](dff4ebc9c5...9b67b6fa77)

---
updated-dependencies:
- dependency-name: igvm_defs
  dependency-version: 9b67b6fa774f4a842718c5c70645973fe73ef616
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 14:25:01 +00:00
Wei Liu
78a16227d2 scripts: Exit create-cloud-init.sh on error
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-09-22 14:24:50 +00:00
Maximilian Güntner
66aa0743f0 vmm: allow net devices without ip and mask
This change enables easier integration with third-party
tools by removing the requirement for a dummy IP address
when configuring tap devices. The modification applies to
both CLI and API interactions.

Previously, cloud-hypervisor would automatically set a
default static IP address (192.168.249.1) if none was provided.

This could lead to:

* multiple devices without explicit IP configurations
  would end up with the same default IP
* unnecessary inclusion of this IP in firewall rules
* the IP address could clash with host networking and
  routing

This introduces a new constraint:
When providing an IP, the mask must also be provided.

Removes warnings introduced in #7179.
Closes issue #7083.

Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-09-22 14:12:47 +00:00
Maximilian Güntner
d28d9eb34e virtio-devices: refactor VSOCK "connect" parsing
The function `read_local_stream_port` had no proper handling for
unexpected or incomplete input.
When the control socket of the VSOCK device was closed without sending
the expected `CONNECT <PORT>\n` statement completely, the thread
got stuck in an infinite loop as it attempted to read from a closed
socket over and over again which never returned any data.

This resulted in the thread responsible for `epoll` being completely
blocked. New VSOCK connections could not be established and existing
ones became defunct, effectively leading to a Denial of Service of
the entire VSOCK device.

The issue can be reproduced by opening a socket and immediately
closing it.

```
socat - UNIX-CONNECT:/socket.vsock
<Ctrl-C>
```

Instead of applying a quick fix by handling the `EPOLLHUP` event before
reading, the function is refactored to remove the error-prone `while`
loop and multiple `read`s.
Notably, we now check if the number of bytes read is zero, which occurs
when `event_set == EPOLLHUP | EPOLLIN`, indicating that the socket has
been closed by the client.

Additionally, the actual parsing code is now extracted into a dedicated
function that is tested.

Fixes: #6798
Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-09-17 17:10:12 +00:00
Muminul Islam
1e8996f94f vmm: hypervisor: simplify VM creation API
For MSHV customers don't want to make everything
default during partition creation. For example
nested support, some synthetic features could be
controlled from CLI through platform argument.
Create_vm API getting messy after adding more flags.
This patch introduces common data struct to be passed
from vmm crate to hypervisor crate during partition creation.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-17 16:40:10 +00:00
Bo Chen
f122398262 misc: Fix beta clippy issues
Fixed with 'cargo clippy --fix' mostly.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-09-17 03:59:57 +00:00
Anirudh Rayabharam
10fb713218 hypervisor: mshv: handle reset intercepts for arm64
Handle MSHV reset intercepts on arm64 such that guests can gracefully
shutdown/reboot instead of panicking due to unhandled intercept.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-09-17 01:34:39 +00:00
dependabot[bot]
90b0dc911c build: Bump epoll from 4.3.3 to 4.4.0
Bumps [epoll](https://github.com/nathansizemore/epoll) from 4.3.3 to 4.4.0.
- [Release notes](https://github.com/nathansizemore/epoll/releases)
- [Commits](https://github.com/nathansizemore/epoll/compare/4.3.3...4.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-16 23:52:39 +00:00
dependabot[bot]
79fe396da9 build: Bump tj-actions/changed-files from 46 to 47
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 46 to 47.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](https://github.com/tj-actions/changed-files/compare/v46...v47)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: '47'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-16 00:23:42 +00:00
dependabot[bot]
72dc280a0c build: Bump async-process from 2.4.0 to 2.5.0
Bumps [async-process](https://github.com/smol-rs/async-process) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/smol-rs/async-process/releases)
- [Changelog](https://github.com/smol-rs/async-process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-process/compare/v2.4.0...v2.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-16 00:03:02 +00:00
Muminul Islam
ad9a1878bf hypervisor: remove invalid url
Reference link to set_device_attribut for aarch64
is invalid. Looks like the code browsing does not
have the reference anymore.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-13 08:30:58 +00:00
Philipp Schuster
8fd8523042 vmm: add info! message on graceful shutdown
This message makes it easier to confirm a successful shutdown when
scanning logs during development and in production. If the message is
missing and the last log entry is not an error, the most likely cause
is a livelock (e.g. contention on a lock) introduced while developing
new Cloud Hypervisor features.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-13 07:43:29 +00:00
dependabot[bot]
d002090afe build: Bump anyhow from 1.0.98 to 1.0.99
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.98 to 1.0.99.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.98...1.0.99)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-12 23:53:47 +00:00
Bo Chen
95e3c8f8fd build: Release v48.0
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-09-12 20:23:29 +00:00
Peter Oskolkov
5f399fc06d vmm: fix hotplugging when max_cpus > 255
Signed-off-by: Peter Oskolkov <posk@posk.io>
2025-09-12 07:23:55 +00:00
dependabot[bot]
43a6a914b8 build: Bump ssh2 from 0.9.4 to 0.9.5
Bumps [ssh2](https://github.com/alexcrichton/ssh2-rs) from 0.9.4 to 0.9.5.
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/0.9.4...0.9.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 23:52:25 +00:00
Bo Chen
ad3f94638f docs: Clarify our policy on AI generated code
Fix: #7162

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-09-11 17:40:51 +00:00
dependabot[bot]
4dd635a56a build: Bump bitflags from 2.9.3 to 2.9.4
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.9.3 to 2.9.4.
- [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.9.3...2.9.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 23:54:06 +00:00
Philipp Schuster
1179a1a1c9 vmm: refactor alignment
Context [0].

[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7256#discussion_r2298538384

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Philipp Schuster
c995b72384 build: treewide: clippy: collapse nested ifs, use let chains
This bumps the MSRV to 1.88 (also, Rust edition 2024 is mandatory).

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Philipp Schuster
f73a6c8d8e build: treewide: clippy for edition 2024
This commit includes all simple clippy fixes excluding the
collapsing of nested ifs using the let-chains feature. This
follows in the next commit.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Philipp Schuster
363273111a build: treewide: fmt for edition 2024
`cargo +nightly fmt`

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Philipp Schuster
061351d82d build: upgrade whole* workspace to Rust edition 2024
This upgrades the Cargo workspace to Rust edition 2024 to keep the
code base clean and up to date.

The commit only contains the adjustments to the Cargo.toml files and
basic compiler error fixes. Also, this commit includes new SAFETY
comments as discussed in [1]. The changes were not automatically
fixed by `cargo fix --edition` but needed manual adjustments.

Apart from that, all formatting and clippy adjustments follow in
subsequent commits.

*
As only exception, workspace member net_gen sticks to edition 2021
for now as discussed in [0].

[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7295#discussion_r2310851041
[1] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7256#issuecomment-3271888674

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
dependabot[bot]
5790bcefee build: Bump miniz_oxide from 0.8.8 to 0.8.9
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.8.8 to 0.8.9.
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 00:01:54 +00:00
Anirudh Rayabharam
86c736fe76 build: bump mshv and vfio crates
Bump mshv-ioctls and mshv-bindings to 0.6.0. Most notably, this version
contains fixes and new bindings for arm64 guests.

Bump the vfio crates too so that they point to the latest mshv crates.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-09-09 22:58:01 +00:00
Wei Liu
5737e58f29 tests: Use serial console in test_cpu_hotplug
Virtio console is activated much later in boot. The output it spits out
lacks the initial CPU configuration of the guest.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-09-09 21:58:42 +00:00
Alyssa Ross
e4af58b88e arch: aarch64: fdt: reduce log verbosity
This module warns for a lot of routine things that the user cannot do
anything about.

Closes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7220
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 17:41:05 +00:00
Alyssa Ross
093f62858f seccomp: avoid hardcoding ioctl numbers
These can differ between platforms, so it's better to use centralized
definitions of them.  We can't currently do this for the KVM and VFIO
ioctls, because the corresponding crates don't publicly expose the
ioctl numbers.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 16:43:35 +00:00
Alyssa Ross
305bec056f arch: aarch64: fdt: replace broken link
The previously linked file was converted to ReStructuredText, then
later removed from the kernel, with part of the justification being
"Most of what booting-without-of.rst contains is now in the DT
specification", so point to that instead.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 16:34:26 +00:00
Alyssa Ross
6cac99bd76 vmm: error if landlock can't be enabled
Since the user has to explicitly ask for Landlock to be enabled in
Cloud Hypervisor, it's surprising that, even when they've done that,
Landlock will silently not be enabled if the kernel doesn't support
it.

To prevent accidental absence of a desired security protection, exit
with an error if Landlock, or the one feature of it we use in Cloud
Hypervisor (file access) is not supported.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 15:08:24 +00:00
Alyssa Ross
533d3a85d1 vmm: fix landlock on aarch64
arch::aarch64::fdt::create_cpu_nodes will always look at this if it
exists.  (If it doesn't exist, this is a no-op —
add_rule_with_access() won't add rules for paths that don't exist.)

Fixes: b3e5738b4 ("vmm: Introduce ApplyLandlock trait")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 11:53:45 +00:00
dependabot[bot]
c7eac0f65a build: Bump clap from 4.5.13 to 4.5.47
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.13 to 4.5.47.
- [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.13...clap_complete-v4.5.47)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 11:13:10 +00:00
Muminul Islam
e7e850bbdd tests: enable more test cases for MSHV
MSHV now supports movable pages i.e VA backed guest.
Also with more features and stability in the MSHV
Kernel drives MSHV now supports more test scenario.
This patch enables more integration test cases.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-09 10:10:53 +00:00
Alyssa Ross
08b197bbc1 vmm: fix vsock with landlock
Without write access to the directory the socket will go in, it's not
possible to create the socket.

I've tested outgoing connections from the VM, and they don't seem to
need read permissions on that directory to connect to a socket on the
host.

Fixes: b3e5738b4 ("vmm: Introduce ApplyLandlock trait")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 10:09:22 +00:00
Alyssa Ross
3259234e58 vmm: drop unnecessary copies
path_beneath_rules() just needs the paths given to it to be
AsRef<Path>, so there's no need to create new PathBufs for it.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-09 04:23:13 +00:00
Peter Oskolkov
05d222f0eb vmm: raise the (v)CPU limit on kvm/x86_64
Raise the max number of supported (v)CPUs on kvm x86_64 hosts
to 8192 (the max allowed value of CONFIG_NR_CPUS in the Linux kernel).

Other platfroms keep their existing CPU limits pending further
development and testing.

The change has been tested on Intel and AMD hosts.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-09-08 22:54:31 +00:00
Peter Oskolkov
57bc78da4f arch: x86_64: make MAX_SUPPORTED_CPUS_LEGACY public
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-09-08 22:54:31 +00:00
Alyssa Ross
47cff7c37f vmm: allow TCGETS2/TCSETS2 where TCGETS/TCSETS are
These are now used by Cloud Hypervisor when linked with Glibc 2.42.

These values should be correct for all currently supported Cloud
Hypervisor platforms, although they are not for all Linux platforms.

Closes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7276
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-09-06 13:33:25 +00:00
dependabot[bot]
3f5c719705 build: Bump crate-ci/typos from 1.36.1 to 1.36.2
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.36.1 to 1.36.2.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.36.1...v1.36.2)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.36.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-06 00:12:14 +00:00
dependabot[bot]
706b56e97d build: Bump async-trait from 0.1.88 to 0.1.89
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.88 to 0.1.89.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.88...0.1.89)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 23:50:25 +00:00
Shubham Chakrawar
2d9e243163 misc: Remove SGX support from Cloud Hypervisor
This commit removes the SGX support from cloud hypervisor. SGX support
was deprecated in May as part of #7090.

Signed-off-by: Shubham Chakrawar <schakrawar@crusoe.ai>
2025-09-05 18:08:36 +00:00
dependabot[bot]
7281459bf9 build: Bump actions/setup-python from 5 to 6
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 00:07:57 +00:00
dependabot[bot]
9bf4696b09 build: Bump libssh2-sys from 0.3.0 to 0.3.1
Bumps [libssh2-sys](https://github.com/alexcrichton/ssh2-rs) from 0.3.0 to 0.3.1.
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/libssh2-sys-0.3.0...libssh2-sys-0.3.1)

---
updated-dependencies:
- dependency-name: libssh2-sys
  dependency-version: 0.3.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 23:54:35 +00:00
dependabot[bot]
f7f79642ab build: Bump io-uring from 0.6.4 to 0.7.10
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.6.4 to 0.7.10.
- [Commits](https://github.com/tokio-rs/io-uring/commits)

---
updated-dependencies:
- dependency-name: io-uring
  dependency-version: 0.7.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 16:49:07 +00:00
dependabot[bot]
1cc193ea3c build: Bump anstyle from 1.0.8 to 1.0.11
Bumps [anstyle](https://github.com/rust-cli/anstyle) from 1.0.8 to 1.0.11.
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.8...v1.0.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 13:14:17 +00:00
dependabot[bot]
676fb93c1a build: Bump crate-ci/typos from 1.35.7 to 1.36.1
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.7 to 1.36.1.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.7...v1.36.1)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.36.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 11:19:34 +00:00
dependabot[bot]
f7e72456b9 build: Bump anstyle-parse from 0.2.6 to 0.2.7
Bumps [anstyle-parse](https://github.com/rust-cli/anstyle) from 0.2.6 to 0.2.7.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.6...anstyle-parse-v0.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 11:08:18 +00:00
dependabot[bot]
bd22190043 build: Bump uuid from 1.17.0 to 1.18.1
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.17.0 to 1.18.1.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.17.0...v1.18.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-04 08:12:29 +00:00
dependabot[bot]
92325fc073 build: Bump zvariant from 5.6.0 to 5.7.0
Bumps [zvariant](https://github.com/dbus2/zbus) from 5.6.0 to 5.7.0.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zvariant-5.6.0...zvariant-5.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-03 18:55:17 +00:00
Muminul Islam
1ca6c159ef tests: option to override default migratable version
This patch gives user an option to override the
default migratable version to any later release.
This option makes MSHV specific tests suitable for
tests since MSHV is stable after some breaking changes.
This patch is also necessary for MSHV CI.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-03 18:51:24 +00:00
dependabot[bot]
c38596d6d3 build: Bump serde_json from 1.0.120 to 1.0.143
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.120 to 1.0.143.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.120...v1.0.143)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-02 23:32:14 +00:00
dependabot[bot]
456f9b3871 build: Bump bitflags from 2.9.2 to 2.9.3
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.9.2 to 2.9.3.
- [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.9.2...2.9.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-02 21:41:41 +00:00
dependabot[bot]
f68880600c build: Bump crate-ci/typos from 1.35.6 to 1.35.7
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.6 to 1.35.7.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.6...v1.35.7)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-02 16:31:43 +00:00
Philipp Schuster
c3a809696a docs: add Safety section to unsafe functions
This step was done manually by searching for "unsafe fn" in
the code base and adding corresponding Safety sections.
`clippy::missing_safety_doc` only works for public functions
but none of the corresponding functions is public.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-02 16:31:25 +00:00
Muminul Islam
a9d6807522 block: batch submit requests for fixed VHD
Updated VHD async implementation to call the batch submit
method via the raw async IO layer.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
c4bab33020 block: Enable request submission in batch when using io_uring
Implement the batch submission function for raw disk, default it is
enabled. After parsing the requests this method is
called for better IO latency and bandwidth.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
245bce23fa block, virtio-devices: Support request submission in batch
Cache and batch IO requests after parsing all
items in the queue, improving performance—especially
for small block sizes—by reducing per-request overhead.

Introduced two methods in the AsyncIo trait for batch
submission, with implementation in the raw disk backend.
This method should be called during/after parsing all block IO requests
in the available queue. If the batch submission is not enabled, by
default it does the old way of submitting requests.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
67ab81874a block: virtio-devices: block: Clarify the return of execute_async()
Instead of returning boolean return an struct of completion status
so that it can be cached for batch submission.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
dependabot[bot]
8b2af1a2c8 build: Bump crate-ci/typos from 1.35.5 to 1.35.6
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.5 to 1.35.6.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.5...v1.35.6)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-29 00:14:07 +00:00
dependabot[bot]
41930d11f7 build: Bump syn from 2.0.104 to 2.0.106
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.104 to 2.0.106.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.104...2.0.106)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-28 23:51:00 +00:00
dependabot[bot]
9c85fbb1af build: Bump proc-macro2 from 1.0.95 to 1.0.101
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.95 to 1.0.101.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.95...1.0.101)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-28 18:36:49 +00:00
dependabot[bot]
5357761c37 build: Bump async-io from 2.4.1 to 2.5.0
Bumps [async-io](https://github.com/smol-rs/async-io) from 2.4.1 to 2.5.0.
- [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.4.1...v2.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 20:36:12 +00:00
dependabot[bot]
bec975a7fc build: Bump wait-timeout from 0.2.0 to 0.2.1
Bumps [wait-timeout](https://github.com/alexcrichton/wait-timeout) from 0.2.0 to 0.2.1.
- [Commits](https://github.com/alexcrichton/wait-timeout/compare/0.2.0...0.2.1)

---
updated-dependencies:
- dependency-name: wait-timeout
  dependency-version: 0.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 18:19:48 +00:00
Songqian Li
92370e8ff1 block: Using feature bits to check the read-only flag
This patch changes the read-only check using acked features bit, which
will help to check more features.

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-26 15:45:45 +00:00
dependabot[bot]
4a1eb0c485 build: Bump cc from 1.2.27 to 1.2.34
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.27 to 1.2.34.
- [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.2.27...cc-v1.2.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 14:47:49 +00:00
Peter Oskolkov
6e6cf099ef hypervisor: enable x2apic API in kvm on x86_64
Also tweak extended interrupt handlings, as needed.

Most credit should go to Neel Natu, who figured out the magic
bits needed to make things work and provided detailed comments.

This patch is still NOOP, as VM config allows only up to
254 vCPUs on x86_64.

Note: changes in this and related previous patches/PRs have
only been tested on Linux hosts running on Intel x86_64 hardware.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-25 23:20:19 +00:00
Anirudh Rayabharam
6e002defe2 tests: remove redundant arch check in bzimage test
test_direct_kernel_boot_bzimage runs only on x86, so the cfg!() branch
for selecting grep_cmd is unnecessary. Remove it for clarity.

Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
2025-08-24 16:37:47 +00:00
Philipp Schuster
a51998605a net_util: add Tap::if_name_as_str
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-23 08:43:33 +00:00
Philipp Schuster
b8be33dff7 net_util: tap: remove needless copy
One can call `to_vec()` anyway if one needs an owned copy. This change
further helps to prevent needless copies in upcoming changes.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-23 08:43:33 +00:00
dependabot[bot]
3864230430 build: Bump autocfg from 1.4.0 to 1.5.0
Bumps [autocfg](https://github.com/cuviper/autocfg) from 1.4.0 to 1.5.0.
- [Commits](https://github.com/cuviper/autocfg/compare/1.4.0...1.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-23 08:20:59 +00:00
Philipp Schuster
2c6426460e vmm: harmonize bootpath across architectures
On aarch64 and RISC-V, calling load_firmware() through load_kernel()
provides no benefit and only duplicates checks already performed in
load_payload(). load_payload() now directly invokes load_firmware() or
load_kernel(), removing unnecessary indirection and redundancy.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-22 16:41:29 +00:00
Bo Chen
1a63b4b2ff vmm: Consolidate 'load_firmware/kernel' for aarch64 and riscv
Both functions are defined separately for the two architecture with
minor differences.

* `load_firmware()`: call `arch::uefi::load_uefi` which are available on
both architecture;
* `load_kernel()`: manually align to `arch::layout::KERNEL_START` 2MB
for both architecture (e.g. no-op for `aarch64`);

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-08-21 15:32:05 +00:00
Philipp Schuster
c1f4df600f vmm: cpu_manager: massively accelerate .pause()
With 254 vCPUs, pausing now takes ~4ms instead of >254ms. This
improvement is visible when running `ch-remote pause` and is
particularly important for live migration, where every millisecond
of downtime matters.

For the wait logic, it is fine to stick to the approach of
sleeping 1ms on the first missed ACK as:

1) we have to wait anyway
2) we give time to the OS, enabling it to schedule a vCPU thread next

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-20 12:51:23 +00:00
Ruoqing He
34c5a081aa ci: Enable kvm build test on RISC-V
Enable kvm build test and clippy test on RISC-V 64-bit platform to
ensure whole projects builds properly.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-20 03:20:09 +00:00
dependabot[bot]
3bff69734e build: Bump crate-ci/typos from 1.35.4 to 1.35.5
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.4 to 1.35.5.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.4...v1.35.5)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 02:57:03 +00:00
dependabot[bot]
91d15c331d build: Bump signal-hook-registry from 1.4.2 to 1.4.6
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.2 to 1.4.6.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.2...registry-v1.4.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 18:07:05 +00:00
dependabot[bot]
e454bb629a build: Bump mintex from 0.1.3 to 0.1.4
Bumps [mintex](https://github.com/garypen/mintex) from 0.1.3 to 0.1.4.
- [Commits](https://github.com/garypen/mintex/compare/v0.1.3...v0.1.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 12:37:27 +00:00
dependabot[bot]
09cf8fba5b build: Bump bitflags from 2.9.0 to 2.9.2
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.9.0 to 2.9.2.
- [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.9.0...2.9.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 10:34:42 +00:00
Philipp Schuster
c34baac649 build: fix warnings from latest nightly (1.91)
The underlying problem currently causes unrelated PRs to fail.
This commit fixes that.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-18 10:52:23 +00:00
dependabot[bot]
a132001021 build: Bump smallvec from 1.13.2 to 1.15.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.13.2 to 1.15.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.13.2...v1.15.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-16 00:16:43 +00:00
Peter Oskolkov
2c7d6be3f4 arch: don't construct mptable on x86_64 if too many CPUs
MP table is a legacy device that is incompatible
with x2apic CPU IDs exceeding 254. The Linux kernel
is perfectly happy without MP table in these cases.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-15 19:15:11 +00:00
Philipp Schuster
dd8687aebb vmm: add enum PayloadConfigError validation to improve error reporting
Currently, the following scenarios are supported by Cloud Hypervisor to
bootstrap a VM:

1. provide firmware
2. provide kernel
3. provide kernel + cmdline
4. provide kernel + initrd
5. provide kernel + cmdline + initrd

As the difference between `--firmware` and `--kernel` is not very clear
currently, especially as both use/support a Xen PVH entry, adding this
helps to identify the cause of misconfiguration.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-15 17:08:37 +00:00
Philipp Schuster
dac0638fe8 misc: fix clippy
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-15 10:55:48 +00:00
Philipp Schuster
92f415ea3f build: Bump MSRV to 1.88
This is necessary to use the let-chains feature in a
follow-up. After upgrading to Rust edition 2024, clippy
wants to collapse various if's with let-chains.

Update image to 20250815-0 since MSRV in Dockerfile is updated.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-15 10:55:48 +00:00
dependabot[bot]
78799187e8 build: Bump event-listener from 5.4.0 to 5.4.1
Bumps [event-listener](https://github.com/smol-rs/event-listener) from 5.4.0 to 5.4.1.
- [Release notes](https://github.com/smol-rs/event-listener/releases)
- [Changelog](https://github.com/smol-rs/event-listener/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/event-listener/compare/v5.4.0...v5.4.1)

---
updated-dependencies:
- dependency-name: event-listener
  dependency-version: 5.4.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 00:40:17 +00:00
Songqian Li
9011ff2161 tests: add ivshmem live migration test case
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
5128ee9ba6 devices, vmm: Handle ivshmem bar reprogramming properly
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
51e095c54d ci: add build and quality check for ivshmem feature
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
4c1ee0329e tests: add ivshmem integration test case
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
a09c8329fb fuzz: add ivshmem device config
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
f0febcae3d docs: add ivshmem device introduction
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
2c282a5a54 vmm: ivshmem device support
Signed-off-by: Yi Wang <foxywang@tencent.com>
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
c72414552b devices: introduce ivshmem device
This patch introduces the inter-vm shared memory(ivshmem) device
to share a memory region between multiple processes running
different guests and the host.

This patch supports the basic ivshmem functions like ivshmem-plain
in QEMU[1].

[1] https://www.qemu.org/docs/master/specs/ivshmem-spec.html

Signed-off-by: Yi Wang <foxywang@tencent.com>
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
Songqian Li
bd17c84d3c virtio-devices: move userspace mapping to vm-device
Move UserspaceMapping to vm-device to avoid redefinition since
UserspaceMapping is used by both `virtio-devices` and `device`
crate.

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-14 22:14:34 +00:00
dependabot[bot]
55212b0437 build: Bump crate-ci/typos from 1.35.3 to 1.35.4
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.3 to 1.35.4.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.3...v1.35.4)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-14 17:31:00 +00:00
Peter Oskolkov
84613d4273 arch: enable x2apic mode on x86_64 if max apic id > 254
This patch builds on PRs

https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7231
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7261

As before, the changes won't be effective until config
parsing/validation raises the vCPU limit.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-14 08:39:15 +00:00
Peter Oskolkov
34385e99f2 misc: simplify configure_vcpu() signature on x86_64
It is always called with topology provided, so there is no
need to pass topology as an Option. Simplifying the signature
makes further topology-related changes to arc/src/x86_64 module
simpler.

Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-14 08:39:15 +00:00
dependabot[bot]
10b79431f6 build: Bump linux-loader from d5f39c0 to 5fdaed8
Bumps [linux-loader](https://github.com/rust-vmm/linux-loader) from `d5f39c0` to `5fdaed8`.
- [Release notes](https://github.com/rust-vmm/linux-loader/releases)
- [Commits](d5f39c09d5...5fdaed87dd)

---
updated-dependencies:
- dependency-name: linux-loader
  dependency-version: 5fdaed87ddafc89d6abf0b50195a12d19133000d
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 23:50:30 +00:00
dependabot[bot]
3d5e5f318b build: Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 18:11:18 +00:00
dependabot[bot]
68a1bf38e5 build: Bump gdbstub_arch from 0.3.0 to 0.3.2
Bumps [gdbstub_arch](https://github.com/daniel5151/gdbstub) from 0.3.0 to 0.3.2.
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 07:31:57 +00:00
Peter Oskolkov
6e0403a959 misc: make topology a 4-tuple of u16s
This is the second patch in a series intended to let Cloud Hypervisor
support more than 255 vCPUs in guest VMs; the first patch/commit is
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7231

At the moment, CPU topology in Cloud Hypervisor is using
u8 for components, and somewhat inconsistently:

- struct CpuTopology in vmm/src/vm_config.rs uses four components
  (threads_per_core, cores_per_die, dies_per_package, packages);

- when passed around as a tuple, it is a 3-tuple of u8, with
  some inconsistency:

- in get_x2apic_id in arch/src/x86_64/mod.rs  the three u8
    are assumed to be (correctly)
    threads_per_core, cores_per_die, and dies_per_package, but

- in get_vcpu_topology() in vmm/src/cpu.rs the three-tuple is
    threads_per_core, cores_per_die, and packages (dies_per_package
    is assumed to always be one? not clear).

So for consistency, a 4-tuple is always passed around.

In addition, the types of the tuple components is changed from u8 to
u16, as on x86_64 subcomponents can consume up to 16 bits.

Again, config constraints have not been changed, so this patch
is mostly NOOP.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-13 07:31:22 +00:00
dependabot[bot]
364a0972f0 build: Bump rustversion from 1.0.21 to 1.0.22
Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.21 to 1.0.22.
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.21...1.0.22)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 23:57:55 +00:00
dependabot[bot]
9283f87f90 build: Bump igvm from 01daa63 to dff4ebc
Bumps [igvm](https://github.com/microsoft/igvm) from `01daa63` to `dff4ebc`.
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](01daa631a5...dff4ebc9c5)

---
updated-dependencies:
- dependency-name: igvm
  dependency-version: dff4ebc9c5bd16707ff75de26ccabe2d4dfdbcd8
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 22:06:14 +00:00
dependabot[bot]
458721629c build: Bump zvariant from 5.5.3 to 5.6.0
Bumps [zvariant](https://github.com/dbus2/zbus) from 5.5.3 to 5.6.0.
- [Release notes](https://github.com/dbus2/zbus/releases)
- [Commits](https://github.com/dbus2/zbus/compare/zvariant-5.5.3...zvariant-5.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 18:05:31 +00:00
dependabot[bot]
d70d132a5c build: Bump errno from 0.3.12 to 0.3.13
Bumps [errno](https://github.com/lambda-fairy/rust-errno) from 0.3.12 to 0.3.13.
- [Release notes](https://github.com/lambda-fairy/rust-errno/releases)
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.12...v0.3.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 11:29:15 +00:00
dependabot[bot]
35121c44db build: Bump slab from 0.4.9 to 0.4.11
Bumps [slab](https://github.com/tokio-rs/slab) from 0.4.9 to 0.4.11.
- [Release notes](https://github.com/tokio-rs/slab/releases)
- [Changelog](https://github.com/tokio-rs/slab/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/slab/compare/v0.4.9...v0.4.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 07:44:17 +00:00
Peter Oskolkov
aa8e9cd91a misc: Change cpu ID type from u8 to u32
This is the first change to Cloud Hypervisor in a series of changes
intended to increase the max number of supported vCPUs in guest VMs,
which is currently limited to 255 (254 on x86_64).

No user-visible/behavior changes are expected as a result of
applying this patch, as the type of boot_cpus and related
fields in config structs remains u8 for now, and all configuration
validations remain the same.

Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
2025-08-11 20:31:50 +00:00
Alex Orozco
5d478c534e tests: Add fw_cfg device integration test
This test verifies that we can see custom items added to the fw_cfg
device from inside the guest

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
a70c1b38e7 devices: Add fw_cfg cli options
This allows us to enable/disable the fw_cfg device via the cli

We can also now upload files into the guest vm using fw_cfg_items
via the cli

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
971f552e09 vmm: Add acpi table for fw_cfg device
This allows the fw_cfg device to be recognized by the guest linux
kernel. This becomes more relavnt in the following cl where I add
the option to load files into the guest via fw_cfg. The Linux kernel
already has a fw_cfg driver that will automatically load these files
under /sys when CONFIG_FW_CFG_SYSFS is enabled in the kernel config

For arm we must add fw_cfg to the devices tree

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
edee53ac1a devices: Implement DMA for fw_cfg device
We pass a reference to the guest memory when we create the device
in DeviceManager. This allows us to access the guest memory for DMA.

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
1f51e4525b devices: Add acpi tables to fw_cfg
The acpi tables are created in the same place the acpi tables would be
created for the regular bootflow, except here we add them to the
fw_cfg device to be measured by the fw and then the fw will put the
acpi tables into memory.

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
f0b69d56d0 devices: Add e820/memory_map to fw_cfg device
We build the memory map in the fw_cfg device based on the memory size.

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
623fadfa9d devices: Add kernel cmdline, kernel, and initramfs to fw_cfg device
The kernel and initramfs are passed to the fw_cfg device as
file references. The cmdline is passed directly.

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Alex Orozco
777b7ee11e devices: Add fw_cfg device
Here we add the fw_cfg device as a legacy device to the device manager.
It is guarded behind a fw_cfg flag in vmm at creation of the
DeviceManager. In this cl we implement the fw_cfg device with one
function (signature).

Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-11 17:29:51 +00:00
Philipp Schuster
5226ceb974 misc: switch error output from error! back to stderr
This partially reverts
ed8f347fe6 from #7183 and
6277d7d5f2 from #7201.

# Output how it was merged for v47 (#7066)
```
Error: Cloud Hypervisor exited with the following chain of errors:
 0: Error booting VM
 1: The VM could not boot
 2: Error manipulating firmware file
 3: No such file or directory (os error 2)

Debug Info: VmBoot(VmBoot(FirmwareFile(Os { code: 2, kind: NotFound, message: "No such file or directory" })))
```

# Output after #7183 and #7201
```
cloud-hypervisor: 31.385730ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:27 -- Error: Cloud Hypervisor exited with the following chain of errors:
cloud-hypervisor: 31.417961ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 --   0: Error booting VM
cloud-hypervisor: 31.448078ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 --   1: The VM could not boot
cloud-hypervisor: 31.486711ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 --   2: Error manipulating firmware file
cloud-hypervisor: 31.513331ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 --   3: No such file or directory (os error 2)
cloud-hypervisor: 31.548037ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:44 --
cloud-hypervisor: 31.568045ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:45 -- Debug Info: VmBoot(VmBoot(FirmwareFile(Os { code: 2, kind: NotFound, message: "No such file or directory" })))
```

The "proper logger" has indeed the advantage that messages can
be gracefully redirected to log files etc. However, this makes the
error message hardly readable.

Therefore, I propose to use error!() only for runtime errors messages
but not a pretty-printed version of those.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-08-11 10:41:11 +00:00
Ruoqing He
17195e1a46 vmm: Enable firmware boot for riscv64
Implement firmware boot (UEFI boot) for riscv64 architecture.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-11 10:10:27 +00:00
Ruoqing He
0df4b1ac4f vmm: Define riscv64 UEFI Error
Error::UefiLoad is required for load_firmware to propagate errors
encountered, define it for riscv64.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-11 10:10:27 +00:00
Ruoqing He
2e0ec8095c vmm: Enable uefi_flash field for riscv64
uefi_flash field in memory_manager is required for uefi loading and
booting, enable it for riscv64 architecture.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-11 10:10:27 +00:00
Ruoqing He
ef2bbe5012 arch: riscv: Introduce UEFI module
Provide Error definitions and load_uefi to be referenced while loading
firmware.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-11 10:10:27 +00:00
Ruoqing He
2524b015b8 arch: riscv: Introduce UEFI related constants
Set UEFI_START and UEFI_SIZE for riscv64 layout.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-08-11 10:10:27 +00:00
Demi Marie Obenour
9825397350 misc: option_parser: allow quoting special characters
The option parser did not allow quoting any special characters, which
means that some strings could not be passed via command-line options.
Fix this by allowing double quotes to quote all the special characters,
such as '@', ',', '[', and ']'.  '"' can be escaped by doubling it.  The
implementation uses some tricks to stay modular.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-08-10 11:25:24 +00:00
Songqian Li
a637940be7 ci: Fix link check failed
### Errors in src/main.rs

* [404] <https://github.com/cloud-hypervisor/cloud-hypervisor/issues/new
/n> | Rejected status code (this depends on your "accept" configuration)
: Not Found

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-10 09:14:07 +00:00
Songqian Li
684fb1dfce ci: Improve link checker conditions
Link checker excludes checks on local links and links with variables.

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-10 09:14:07 +00:00
dependabot[bot]
e718e0ad36 build: Bump async-trait from 0.1.86 to 0.1.88
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.86 to 0.1.88.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.86...0.1.88)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-09 01:23:59 +00:00
dependabot[bot]
f87772cd36 build: Bump crate-ci/typos from 1.35.2 to 1.35.3
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.2 to 1.35.3.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.2...v1.35.3)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-09 00:29:54 +00:00
dependabot[bot]
0d9a941a2c build: Bump redox_users from 0.5.0 to 0.5.2
Bumps redox_users from 0.5.0 to 0.5.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 04:58:07 +00:00
dependabot[bot]
4f4940b02a build: Bump crate-ci/typos from 1.35.1 to 1.35.2
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.35.1 to 1.35.2.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.35.1...v1.35.2)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 00:18:56 +00:00
Songqian Li
0bfa160360 hypervisor: Replacing pdf link with new available link
Replacing pdf link with new available link to fix the failed CI.

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-07 16:53:59 +00:00
Songqian Li
530719a57a build: Bump MSRV to 1.87.0
rustc 1.90.0-beta.1 (788da80fc 2025-08-04) suggests using library
feature `unsigned_is_multiple_of`. It is stabled in Rust 1.87.0.

Update image to 20250807-0 since MSRV in Dockerfile is updated.

Signed-off-by: Songqian Li <sionli@tencent.com>
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-08-07 16:53:59 +00:00
Songqian Li
cd2c43b489 misc: Fix beta clippy errors
Fix clippy error: "error: manual implementation of `.is_multiple_of()
`" from rustc 1.90.0-beta.1 (788da80fc 2025-08-04).

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-07 16:53:59 +00:00
Bo Chen
394fd230b0 vmm: acpi: Clarify the return of 'create_acpi_tables_internal'
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-08-06 21:11:27 +00:00
Bo Chen
abcec231eb vmm: acpi: Clarify variable naming in 'create_acpi_tables_internal'
When generating ACPI tables, we are not using "offset", instead we
are using (guest physical) addresses.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-08-06 21:11:27 +00:00
Bo Chen
cda1ea53a5 vmm: acpi: Make 'create_acpi_tables' more flexible
Now 'create_acpi_tables_internal()' can generate ACPI tables with
different dsdt offset, so that it can be reused for generating ACPI
tables for `fw_cfg`.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Alex Orozco <alexorozco@google.com>
2025-08-06 21:11:27 +00:00
dependabot[bot]
e2d2b2f2f0 build: Bump rand from 0.9.1 to 0.9.2
Bumps [rand](https://github.com/rust-random/rand) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/rand_core-0.9.1...rand_core-0.9.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 12:12:45 +00:00
dependabot[bot]
9ee3b29a11 build: Bump crate-ci/typos from 1.34.0 to 1.35.1
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.34.0 to 1.35.1.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.34.0...v1.35.1)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.35.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 08:15:40 +00:00
dependabot[bot]
eb147cb3cc build: Bump rustc-demangle from 0.1.24 to 0.1.26
Bumps [rustc-demangle](https://github.com/rust-lang/rustc-demangle) from 0.1.24 to 0.1.26.
- [Release notes](https://github.com/rust-lang/rustc-demangle/releases)
- [Changelog](https://github.com/rust-lang/rustc-demangle/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rustc-demangle/compare/0.1.24...rustc-demangle-v0.1.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 07:06:06 +00:00
dependabot[bot]
b630b22ed9 build: Bump landlock from 0.4.0 to 0.4.2
Bumps [landlock](https://github.com/landlock-lsm/rust-landlock) from 0.4.0 to 0.4.2.
- [Release notes](https://github.com/landlock-lsm/rust-landlock/releases)
- [Changelog](https://github.com/landlock-lsm/rust-landlock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/landlock-lsm/rust-landlock/compare/v0.4.0...v0.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-02 00:20:14 +00:00
dependabot[bot]
a7645ae9d6 build: Bump async-process from 2.3.0 to 2.4.0
Bumps [async-process](https://github.com/smol-rs/async-process) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/smol-rs/async-process/releases)
- [Changelog](https://github.com/smol-rs/async-process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-process/compare/v2.3.0...v2.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-01 00:05:35 +00:00
dependabot[bot]
254db85a33 build: Bump anyhow from 1.0.94 to 1.0.98
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.94 to 1.0.98.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.94...1.0.98)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 03:29:16 +00:00
dependabot[bot]
16b0e08482 build: Bump tj-actions/changed-files from 40 to 46 in /.github/workflows
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 40 to 46.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](https://github.com/tj-actions/changed-files/compare/v40...v46)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: '46'
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 00:01:11 +00:00
Shubham Chakrawar
8a37e154db ci: Prevent link checker rate limits
Optimize lychee workflow to check only changed
files in pull requests, avoiding excessive API
calls to prevent rate limits.

Fixes #7056

Signed-off-by: Shubham Chakrawar <schakrawar@crusoe.ai>
2025-07-30 22:30:36 +00:00
dependabot[bot]
003e89e8cd build: Bump anstream from 0.6.15 to 0.6.19
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.15 to 0.6.19.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.15...anstream-v0.6.19)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 00:37:23 +00:00
Muminul Islam
8e010f1aa3 vmm: don't configure system if rsdp is not available
In case of CVM guest rsdp is set to none. Unwrapping it
make the vmm crashed. Don't call configure system if the
rsdb address is none.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-07-29 15:55:06 +00:00
dependabot[bot]
7c631b2d1b build: Bump toml_datetime from 0.6.8 to 0.6.11
Bumps [toml_datetime](https://github.com/toml-rs/toml) from 0.6.8 to 0.6.11.
- [Commits](https://github.com/toml-rs/toml/compare/toml_datetime-v0.6.8...toml_datetime-v0.6.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-29 05:33:35 +00:00
dependabot[bot]
ba962a30d5 build: Bump r-efi from 5.2.0 to 5.3.0
Bumps [r-efi](https://github.com/r-efi/r-efi) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/r-efi/r-efi/releases)
- [Changelog](https://github.com/r-efi/r-efi/blob/main/NEWS.md)
- [Commits](https://github.com/r-efi/r-efi/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: r-efi
  dependency-version: 5.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-29 03:50:24 +00:00
Oliver Anderson
8c136041cb build: Use workspace dependencies
Many of the workspace members in the Cloud-hypervisor workspace share
common dependencies. Making these workspace dependencies reduces
duplication and improves maintainability.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
2025-07-28 20:19:27 +00:00
dependabot[bot]
b0bf889d58 build: Bump serde_with from 3.9.0 to 3.14.0
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.9.0 to 3.14.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.9.0...v3.14.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-26 00:03:54 +00:00
Lucas Grosche
2c3e6cd93d docs: Add Windows 11 support information
The current documentation only mentions Windows
server support. Since only minimal adjustments
are needed for Windows 11 support, these were
added where applicable.

Also contains whitespace fixes, adds missing `\`
in example code and adds more cross references.

Signed-off-by: Lucas Grosche <lucas.grosche@cyberus-technology.de>
2025-07-25 22:30:59 +00:00
dependabot[bot]
985dcfbf3e build: Bump async-signal from 0.2.11 to 0.2.12
Bumps [async-signal](https://github.com/smol-rs/async-signal) from 0.2.11 to 0.2.12.
- [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.11...v0.2.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-25 00:38:42 +00:00
Oliver Anderson
511a100842 tpm: Use the same log version as other workspace members
The other workspace members in the Cloud-hypervisor workspace
currently declare log version 0.4.22, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring log as a workspace dependency.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
2025-07-24 23:52:45 +00:00
Wei Liu
8a26380657 performance-metrics: Add all supported formats to block tests
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 23:37:09 +00:00
Wei Liu
76d8d47f6a performance-metrics: Initialize tests after setting overrides
No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 23:37:09 +00:00
dependabot[bot]
423280fb96 build: Bump enumflags2 from 0.7.10 to 0.7.12
Bumps [enumflags2](https://github.com/meithecatte/enumflags2) from 0.7.10 to 0.7.12.
- [Release notes](https://github.com/meithecatte/enumflags2/releases)
- [Commits](https://github.com/meithecatte/enumflags2/compare/v0.7.10...v0.7.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-24 16:47:13 +00:00
Wei Liu
5f2392c095 tests: Avoid repeatedly downloading files from GitHub
Running one or two tests in a tight loop can cause the download
functions to quickly hit GitHub's API rate limit. That causes the test
script to fail for no apparent reason.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 16:46:43 +00:00
Wei Liu
2d9fc3beb6 tests: Reenable test_virtio_block_dynamic_vhdx_expand
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 01:06:12 +00:00
Wei Liu
4cae96f070 tests: Avoid races in the VHDX expansion test
Generate the data disk under a temporary directory so that multiple
instances of the test suites can run at the same time.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 01:06:12 +00:00
Wei Liu
f6568042ce tests: Fix an error message in VHDX expansion test
The VHDX image is generated directly, not converted from a RAW image.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-24 01:06:12 +00:00
Oliver Anderson
2ae5b2567b tpm: Use the same libc crate version as other workspace members
The other workspace members in the Cloud-hypervisor workspace
currently declare libc crate version 0.2.167, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring libc as a workspace dependency.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
2025-07-24 01:05:08 +00:00
Oliver Anderson
6d70c570f3 tpm: Use the same anyhow version as other workspace members
The other workspace members in the Cloud-hypervisor workspace
currently declare anyhow version 1.0.94, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring anyhow as a workspace dependency.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
2025-07-23 16:29:34 +00:00
Wei Liu
930a911862 block: Simplify AsyncAdaptor
It shouldn't be necessary to lock the file for the adaptor. This removes
two layers of indirection for QcowDiskSync and VhdxDiskSync.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-22 22:00:35 +00:00
Bo Chen
03b22a510d tests: Disable 'test_virtio_block_dynamic_vhdx_expand'
This issue is tracked via #7209.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-07-22 21:06:54 +00:00
Bo Chen
62001b65e9 build: Release v47.0
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-07-22 21:06:54 +00:00
Wei Liu
4be2ca4c10 vhost_user_net: Use Mutex::get_mut() where possible
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-17 19:20:59 +00:00
Wei Liu
5716af09a5 vhost_user_block: Use Mutex::get_mut() where possible
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-17 19:20:59 +00:00
Wei Liu
4ea40b4bea rate_limiter: Use Mutex::get_mut() in update_buckets
There is no need to lock. That function already holds a mutable
reference to self.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-17 19:20:59 +00:00
Jean-Philippe Brucker
4528e2f1ea devices: rtc_pl031: Disable broken interrupt
The PL031 RTC provides two features: a real-time counter and an alarm
interrupt. To use the alarm, the driver normally writes a time value
into the match register RTCMR, and when the counter reaches that value
the device triggers the interrupt.

At the moment the implementation ignores programming of the alarm, as
the feature seems rarely used in VMs. However the interrupt is still
triggered arbitrarily when the guest writes to registers, and the line
is never cleared. This really confuses the Linux driver, which loops in
the interrupt handler until Linux realizes that no one is dealing with
the interrupt (200000 unanswered calls) and disables the handler.

One way to fix this would be implementing the alarm function properly,
which isn't too difficult but requires adding some async timer logic
which probably won't ever get used. In addition the device's interrupt
is level-triggered and we don't support level interrupts at the moment,
though we could probably get away with changing this interrupt to edge.

The simplest fix, though, is to just disable the interrupt logic
entirely, so that the alarm function still doesn't work but the guest
doesn't see spurious interrupts.

Add a default() implementation to satisfy clippy's new_without_default
check, since Rtc::new() doesn't take a parameter after this change.

Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
2025-07-17 17:21:05 +00:00
Bo Chen
987ad11c90 main: Report errors with 'error!()'
This was missed from #7183, likely because `eprint!` is used instead of
`eprintln!`.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-07-17 16:18:56 +00:00
Wei Liu
cea708deb9 performance-metrics: Fix the names of the kernels
In 2b05753716, the names of the reference kernels are changed.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-16 20:20:32 +00:00
Songqian Li
e32fa593e5 build: clean up unused dependencies
Signed-off-by: Songqian Li <sionli@tencent.com>
2025-07-15 07:16:36 +00:00
Alyssa Ross
ec8fceb4a6 virtio-devices: stop corrupting vsock commands
The read_exact() call was introduced in 82ac114b8 ("virtio-devices:
vsock: handle short read in muxer") to solve a crash when a connection
disconnected without sending any data, but it introduced a problem of
its own: because the socket is non-blocking, read_exact() may read
some data, then return ErrorKind::WouldBlock.  In that case, the data
it read will be discarded.  So for example if it read "CONNECT ",
and then nothing else was available to read yet, "CONNECT " would be
discarded, and so the next time this function was called, when epoll
triggered again for the socket, only the following data would end up
in command.buf, causing an error due to just a port number being an
invalid command.

Contrary to that commit message, this code was actually designed to
handle short reads just fine — in the case of a short read, it stores
the data it has read in command, and returns
Error::UnixRead(ErrorKind::WouldBlock), which is ignored by the
caller, and the function gets called again when there is more data to
read, building up command potentially over the course of several
reads.  The only thing it didn't handle correctly, as far as I can
tell, was a 0-byte read, which happens when a client disconnects from
the socket without writing anything.  All that's needed to fix this is
to avoid an invalid subtraction in that case, so this change reverts
82ac114b8, fixing the issue with partial commands being discarded, and
instead handles the 0-byte read by using slice::get, and treating an
empty command as an incomplete command, which of course it is.

Fixes: 82ac114b8 ("virtio-devices: vsock: handle short read in muxer")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-07-14 18:07:07 +00:00
Alyssa Ross
01aed9733c build: add missing dependency features
This makes it possible to run cargo test just for the virtio-devices
crate (as long as either KVM or MSHV is specified).

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-07-14 18:06:54 +00:00
Nuno Das Neves
a5cd1b4fbe build: Bump mshv-ioctls and mshv-bindings to v0.5.2
Also update the version in the fuzz crate.

Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
2025-07-12 01:17:26 +00:00
Muminul Islam
b268e88ba3 virtio-devices: remove unnecessary parentheses
Cargo fuzz build report an warning:

warning: unnecessary parentheses around closure body
--> virtio-devices/src/iommu.rs:578:41
|
578 |.retain(|&x, _| (x < req.virt_start || x > req.virt_end));
|                                         ^
|
= note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
|
578 -.retain(|&x, _| (x < req.virt_start || x > req.virt_end));
578 +.retain(|&x, _| x < req.virt_start || x > req.virt_end);
|

warning: `virtio-devices` (lib) generated 1 warning
(run `cargo fix --lib -p virtio-devices` to apply 1 suggestion)

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-07-11 22:02:15 +00:00
dependabot[bot]
0659eaeba1 build: Bump async-signal from 0.2.10 to 0.2.11
Bumps [async-signal](https://github.com/smol-rs/async-signal) from 0.2.10 to 0.2.11.
- [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.10...v0.2.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-11 00:38:49 +00:00
Bo Chen
96528f84f9 build: Bump gdbstub from 0.7.1 to 0.7.6
Bumps [gdbstub](https://github.com/daniel5151/gdbstub) from 0.7.1 to 0.7.6.
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.7.1...0.7.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-07-10 19:46:28 +00:00
Ruoqing He
6da5c32fd9 hypervisor: aarch64: Use offset_of for nested fields
`std::mem::offset_of` could be used for calculating nested fields, use
this feature to shorten aarch64 reg offset calculation.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-07-10 16:39:39 +00:00
Ruoqing He
07cc1f6545 hypervisor: aarch64: Remove manually implemented offset_of
Manually implemented `offset_of` in `arch/aarch64/mod.rs` is not used
now, remove it.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-07-10 16:39:39 +00:00
Ruoqing He
008f259aff hypervisor: aarch64: Use offset_of from std::mem
`std::mem::offset_of` is stabilized since Rust 1.77, let's use
implementation provided by std instead of manual implementation.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-07-10 16:39:39 +00:00
Ruoqing He
aa6fefa80f hypervisor: riscv64: Remove manually implemented offset_of
Manually implemented `_offset_of` and `offset_of` in
`arch/riscv64/mod.rs` are not used now, remove them.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-07-10 16:39:39 +00:00
Ruoqing He
87e74719ec hypervisor: riscv64: Use offset_of from std::mem
`std::mem::offset_of` supports calculating offset of nested structures,
let's use implementation provided by std instead of manual
implementation.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-07-10 16:39:39 +00:00
Maximilian Güntner
072f06ff4c misc: vhost_user_net: replace eprintln with log::error
Other lines are already logged using `log::error!` and
`env_logger` is initialized before calling
`start_net_backend` in `main()`.

Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-07-10 16:36:54 +00:00
Maximilian Güntner
50b33db718 vmm: replace eprintln with log::error
Unify log formatting and printing as `eprintln!` and `log::error!`
would be used alongside each other.
When using e.g. `env_logger` lines printed with `eprintln!` would
lack formatting / colors.
Currently only relevant in `ch-remote` + `cli_print_error_chain`.

Note that the replaced messages now also end up in the logfile of
`cloud-hypervisor` when configured and not any longer in stderr.

Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-07-10 16:36:54 +00:00
Maximilian Güntner
19dc733267 ch-remote: add env_logger, log messages to stderr
Until now all messages generated using `log::level!`
(e.g., `warn!`) have not been printed as `ch-remote` did not
register a logger.
Furthermore, replace all `eprintln!` with `error!`
to align formatting for consistency.

Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-07-10 16:36:54 +00:00
Maximilian Güntner
6ba949d741 build: consolidate env_logger to workspace, update to 0.11.8
Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-07-10 16:36:54 +00:00
Philipp Schuster
9d4408ba76 vmm: add directory path to error message
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-07-10 16:24:50 +00:00
Maximilian Güntner
f9c134471a vmm: warn about deprecation of default IP address + mask
Issue: #7083

Signed-off-by: Maximilian Güntner <code@mguentner.de>
2025-07-08 19:05:45 +00:00
ninollei
3d5b4d0b0c vmm: acpi: Use correct table name in error message
Fix a copy-paste error using the wrong table name in the assertion

Signed-off-by: ninollei <ninollx@hotmail.com>
2025-07-08 09:02:40 +00:00
dependabot[bot]
ea32b67098 build: Bump proc-macro-crate from 3.2.0 to 3.3.0
Bumps [proc-macro-crate](https://github.com/bkchr/proc-macro-crate) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/bkchr/proc-macro-crate/releases)
- [Commits](https://github.com/bkchr/proc-macro-crate/compare/v3.2.0...v3.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 17:23:51 +00:00
Jinank Jain
190d90196f build: Bump vfio and all the dependent crates to latest version
Recently vfio crates have moved to crates.io, thus we should start
consuming the crate from crates.io instead git url.

This results in better versioning instead of tracking some git commit
sha.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-07-07 03:05:38 +00:00
Jinank Jain
fe422a45af build: Move away from actions-rs/cross
Since action-rs/cross is deprecrated, thus move to
houseabsolute/actions-rust-cross.

We should pin the cross-version to the latest version to fix the build
issues with virtio-bindings crate.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-07-07 03:05:38 +00:00
Wei Liu
da5fae3814 docs: Fix the chown command in macvtap-bridge.md
When invoking the script chown shows a warning.

    chown: warning: '.' should be ':': ‘1000.1000’

From `info coreutils 'chown invocation'`.

   Some older scripts may still use ‘.’ in place of the ‘:’ separator.
POSIX 1003.1-2001 (*note Standards conformance::) does not require
support for that, but for backward compatibility GNU ‘chown’ supports
‘.’ so long as no ambiguity results, although it issues a warning and
support may be removed in future versions.  New scripts should avoid the
use of ‘.’ because it is not portable, and because it has undesirable
results if the entire OWNER‘.’GROUP happens to identify a user whose
name contains ‘.’.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-01 15:12:03 +00:00
dependabot[bot]
8a78043e2f build: Bump crate-ci/typos from 1.33.1 to 1.34.0
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.33.1 to 1.34.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.33.1...v1.34.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 02:50:46 +00:00
Wei Liu
fdeb778210 block: Add back UUID crate's v4 feature
That feature was dropped when consolidating the UUID dependency because
somehow building the whole project worked. The CI system was happy.

However, building the block crate alone is broken. The vhdx code uses
Uuid::new_v4, which requires `v4` to be enabled.

Add the feature back.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-06-30 10:54:54 +00:00
dependabot[bot]
13c222a879 build: Bump proc-macro2 from 1.0.93 to 1.0.95
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.93 to 1.0.95.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.95)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-28 00:18:30 +00:00
dependabot[bot]
b27d9ccfab build: Bump rustix from 0.38.34 to 0.38.44
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.34 to 0.38.44.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGES.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.34...v0.38.44)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-26 23:56:47 +00:00
Philipp Schuster
d580ed55c6 seccomp: add SYS_getcwd (79) to support proper Rust backtraces
When a proper Rust backtrace is printed, the Rust std wants to use the
SYS_getcwd(79) system call to prettify some paths while printing. In
Cloud Hypervisor, this is at least relevant for printing panics or if
a `anyhow::Error` value is printed using `{e:?}` (but not `{e:#?}`).

The syscall cause can be found in `impl fmt::Display for Backtrace {}`
in `library/std/src/backtrace.rs`.

Without this addition, the seccomp violation of the SYS_getcwd (79)
hinders the proper error message including a full backtrace from showing
up. This annoying behaviour already delayed many debugging efforts. With
this fix, things just work. The new syscall itself should be pretty
harmless for normal operation.

```
thread 'vmm' panicked at virtio-devices/src/rng.rs:224:9:
Yikes, things went horribly wrong!

==== Possible seccomp violation ====
Try running with `strace -ff` to identify the cause and open an issue: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/new
[1]    287683 invalid system call (core dumped)  RUST_BACKTRACE=full cargo run --bin cloud-hypervisor -- --api-socket  --kerne
```

```
thread 'vmm' panicked at virtio-devices/src/rng.rs:224:9:
Yikes, things went horribly wrong!
stack backtrace:
   0:     0x557d91286b62 - std::backtrace_rs::backtrace::libunwind::trace::hc20b48b31ee52608
                               at /rustc/17067e9ac6d7ecb70e50f92c1944e545188d2359/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
   1:     0x557d91286b62 - std::backtrace_rs::backtrace::trace_unsynchronized::h5d207cd20f193d88
                               at /rustc/17067e9ac6d7ecb70e50f92c1944e545188d2359/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14

...

  67:                0x0 - <unknown>
Error: Cloud Hypervisor exited with the following error:
  Failed to join on VMM thread: Any { .. }

Debug Info: ThreadJoin(Any { .. })
```

- add any panic, for example into the create or drop function of a
  device
- add --seccomp=true|log to analyze the situation

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-26 20:50:57 +00:00
dependabot[bot]
2cb8c41adc build: Bump remain from 0.2.14 to 0.2.15
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.14 to 0.2.15.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.14...0.2.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-26 00:37:52 +00:00
Philipp Schuster
48b67ed03b net_util: code readability improvements
Small cleanup to improve code readability.
Specifically, refactoring a huge loop body into
a function call.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-25 16:22:16 +00:00
Philipp Schuster
e0f0065cbd net_util: improve Error types
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-25 16:22:16 +00:00
dependabot[bot]
1866a85a3d build: Bump zerocopy from 0.8.24 to 0.8.26
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.8.24 to 0.8.26.
- [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.8.24...v0.8.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-25 10:07:20 +00:00
Hengqi Chen
8338fa642f net_util: Drop duplicated virtio_features_to_tap_offload
The virtio_features_to_tap_offload() defined in ctrl_queue.rs
is duplicated. Remove it and use the one defined in lib.rs
instead.

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
2025-06-24 17:43:22 +00:00
Wei Liu
a5287c6f67 build: Consolidate UUID crate to workspace
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-06-24 16:50:35 +00:00
Philipp Schuster
fe07617f5d misc: add __pycache__ to gitignore
Running `gitlint` locally produces a __pycache__ directory in
`scripts/gitlint/rules/`. It makes sense to exclude this directory.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-24 11:22:00 +00:00
dependabot[bot]
1820c22ba4 build: Bump cc from 1.2.23 to 1.2.27
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.23 to 1.2.27.
- [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.2.23...cc-v1.2.27)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 04:25:02 +00:00
dependabot[bot]
f828e16d62 build: Bump syn from 2.0.87 to 2.0.104
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.87 to 2.0.104.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.87...2.0.104)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 02:37:24 +00:00
Demi Marie Obenour
24998c1672 vmm: do not treat libc::MAP_FAILED as a pointer
It will likely be safely rejected by the kernel, but it's still wrong.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-06-23 09:06:32 +00:00
Wei Liu
821f7994fc build: Bump UUID crate to 1.17.0
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-06-21 14:27:19 +00:00
Philipp Schuster
4182ef91e0 misc: remove once_cell; superseded by std::*
We now have types in the Rust standard library.
Dropping the dependency.

I found this by using the `clippy::pedantic` group.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-21 14:25:20 +00:00
Demi Marie Obenour
100c6d8142 docs: SGX virt changes are upstream
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-06-20 10:21:04 +00:00
Demi Marie Obenour
269976c7b3 block: Remove unnecessary pointer indirection
No functional change intended.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-06-20 10:21:04 +00:00
Demi Marie Obenour
8769b78bf3 arch: x86_64: Require that types to be checksummed are ByteValued
Checksumming a type that has padding would use the padding in the
checksum, which is definitely wrong and is often unsound.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-06-20 10:21:04 +00:00
Philipp Schuster
a991de9955 vmm: streamline Display impl of Error types
Streamlines the code base by using thiserror's #[error] attribute
consistently for implementing `Display`.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-20 10:19:35 +00:00
dependabot[bot]
47c9ddfa7e build: Bump hashbrown from 0.15.2 to 0.15.4
Bumps [hashbrown](https://github.com/rust-lang/hashbrown) from 0.15.2 to 0.15.4.
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/commits/v0.15.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-17 01:49:45 +00:00
Bo Chen
2b05753716 ci: Update reference kernel to 'v6.12.8-20250613'
This bump also includes another release 'ch-release-v6.12.8-20250422'
that changed the naming convention of the released kernel binaries
[1]. As a result, few changes are made to our integration tests and test
scripts.

[1] https://github.com/cloud-hypervisor/linux/releases/tag/ch-release-v6.12.8-20250422

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-06-16 17:59:22 +00:00
Yi Wang
80f4bfac00 block: keep lifetime consistent from input to output
Cargo fuzz build report an error:
error: lifetime flowing from input to output with different syntax can be confusing
   --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/lib.rs:747:13
    |
747 |     fn file(&mut self) -> MutexGuard<F>;
    |             ^^^^^^^^^     ------------- the lifetime gets resolved as `'_`
    |             |
    |             this lifetime flows to the output

error: lifetime flowing from input to output with different syntax can be confusing
  --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/async_io.rs:68:11
   |
68 |     fn fd(&mut self) -> BorrowedDiskFd;
   |           ^^^^^^^^^     -------------- the lifetime gets resolved as `'_`
   |           |
   |           this lifetime flows to the output

Signed-off-by: Yi Wang <foxywang@tencent.com>
2025-06-16 06:25:57 +00:00
dependabot[bot]
b26b09ec0c build: Bump crate-ci/typos from 1.32.0 to 1.33.1
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.32.0 to 1.33.1.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.32.0...v1.33.1)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.33.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-14 00:42:13 +00:00
dependabot[bot]
39a6664e62 build: Bump event-listener from 5.3.1 to 5.4.0
Bumps [event-listener](https://github.com/smol-rs/event-listener) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/smol-rs/event-listener/releases)
- [Changelog](https://github.com/smol-rs/event-listener/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/event-listener/compare/v5.3.1...v5.4.0)

---
updated-dependencies:
- dependency-name: event-listener
  dependency-version: 5.4.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 23:58:27 +00:00
Philipp Schuster
190a11f212 ch-remote: also pretty-print remote server errors
Remote server errors are transferred as raw HTTP body. This way,
we lose the nested structured error information.

This is an attempt to retrieve the errors from the HTTP response
and to align the output with the normal error output.

For example, this produces the following chain of errors. Note
that everything after level 0 was retrieved from the HTTP server
response:

```
Error: ch-remote exited with the following chain of errors:
  0: http client error
  1: Server responded with InternalServerError
  2: Error from API
  3: The disk could not be added to the VM
  4: Failed to validate config
  5: Identifier disk1 is not unique

Debug Info: HttpApiClient(ServerResponse(InternalServerError, Some("Error from API<br>The disk could not be added to the VM<br>Failed to validate config<br>Identifier disk1 is not unique")))
```

In case the JSON can't be parsed properly, ch-remote will print:

```
Error: ch-remote exited with the following chain of errors:
  0: http client error
  X: Can't get remote's error messages from JSON response: EOF while parsing a value at line 1 column 0: body=''

Debug Info: HttpApiClient(ServerResponse(InternalServerError, Some("")))
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
6ea132708c vmm: use Error trait directly with Note for compiler bug
While working on this, I found a subtle but severe compiler bug [0].
To fight the bug with explicitness rather than implicitness (to
prevent weird stuff in the future), this change is beneficial.

The bug is at least in Rust stable 1.34..1.87.

[0]: https://github.com/rust-lang/rust/issues/141673

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
060c9de07f vmm: introduce nice error messages on exit (CHV and ch-remote)
With the foundations of each error type implementing std::error::Error,
we can now nicely walk the `.source()` chain and print an error trace.

This commit introduces improved user-facing error printing when:
- Cloud Hypervisor fails with an error
- ch-remote fails (client error)
- ch-remote fails (remote error)

The additional context is a clear improvement in UX for both users and
developers. In the following example, the new behaviour is shown for
a direct invocation of Cloud Hypervisor leading to a failure. This
looks similar for ch-remote.

```
Old Style
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs /etc/bootitems/linux/initrd_minimal/default`

Error booting VM: VmBoot(LockingError(BlockError(LockDiskImage(AlreadyLocked)))
```

```
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs
/etc/bootitems/linux/initrd_minimal/default`

Error: Cloud Hypervisor exited with the following chain of errors:
  0: Error booting VM
  1: The VM could not boot
  2: Error locking disk images: Another instance likely holds a lock
  3: Cannot lock images of all block devices
  4: Failed to get Write lock for disk image: ./img.raw
  5: The file is already locked

Debug Info: VmBoot(VmBoot(LockingError(DiskLockError(LockDiskImage { error: AlreadyLocked, lock_type: Write, path: "./raw_disk.bin" })))
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
1433763d40 misc: virtio-devices: manual adjustment of special case
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
30ee2c129d misc: vm-migration: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
9bf15ed280 misc: vhost_user_net: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
ed63b352d1 misc: vhost_user_block: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
8e2973fe7c misc: virtio-devices: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
3541cebbf1 misc: tpm: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
1ede418dcc misc: test_infra: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
1b03e59152 misc: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
8f56de713b misc: rate_limiter: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
2100d8c30f misc: performance-metrics: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
a3692144f0 misc: pci: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
192b19c060 misc: option_parser: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
67896333e3 misc: net_util: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
72c8178335 misc: hypervisor: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
1b91aa8ef3 misc: devices: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
5711f31995 misc: ch-remote: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
aebbd1aecd misc: block: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
06a868cb85 misc: arch: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
3f3489e38e misc: api_client: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
d7edd9d51f misc: vmm: streamline error Display::fmt()
The changes were mostly automatically applied using the following
Python script:

```python
import os, re

for root, _, files in os.walk("."):
    for f in files:
        if not f.endswith(".rs"):
            continue
        p = os.path.join(root, f)
        with open(p, "r", encoding="utf-8") as file:
            lines = file.readlines()
        changed = False
        for i in range(len(lines) - 1):
            if re.search(r'#\[error\(".*: \{0[^}]*\}"\)\]', lines[i]) and "#[source]" in lines[i + 1].strip():
                lines[i] = re.sub(r': \{0[^}]*\}"\)\]', '")]', lines[i])
                changed = True
        if changed:
            with open(p, "w", encoding="utf-8") as file:
                file.writelines(lines)
            print("Fixed:", p)
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com

# Conflicts:
#	vmm/src/api/http/mod.rs
2025-06-13 19:55:54 +00:00
Philipp Schuster
4987d63b6a vmm: fix typo
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
53e9c94e68 tests: cleanup test_util module
We can remove the `tests` module as the entire file is only
available when running tests.

Follow-up of #7130 / 1f13165fae.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:02:39 +00:00
dependabot[bot]
9d8bda20e5 build: Bump object from 0.36.5 to 0.36.7
Bumps [object](https://github.com/gimli-rs/object) from 0.36.5 to 0.36.7.
- [Changelog](https://github.com/gimli-rs/object/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/object/compare/0.36.5...0.36.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 00:25:40 +00:00
dependabot[bot]
63d7f562e5 build: Bump houseabsolute/actions-rust-cross from 0 to 1
Bumps [houseabsolute/actions-rust-cross](https://github.com/houseabsolute/actions-rust-cross) from 0 to 1.
- [Release notes](https://github.com/houseabsolute/actions-rust-cross/releases)
- [Changelog](https://github.com/houseabsolute/actions-rust-cross/blob/v1/Changes.md)
- [Commits](https://github.com/houseabsolute/actions-rust-cross/compare/v0...v1)

---
updated-dependencies:
- dependency-name: houseabsolute/actions-rust-cross
  dependency-version: '1'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 00:09:49 +00:00
Philipp Schuster
9bd9c0cb71 misc: replace manual From<T> for *Error with #[from]
This is a small simplification we can use since we use `thiserror`
anyway. Note that `#[from]` implies `#[source]` [0].

[0]: https://docs.rs/thiserror/2.0.12/thiserror/index.html

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-12 15:55:54 +00:00
Philipp Schuster
d594107c0d ch-remote: sort all commands and args alphabetically
Having them sorted alphabetically makes more sense since there are
already many, and the list is growing. This improves the UX for users
and developers.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-12 13:53:55 +00:00
Philipp Schuster
1f13165fae tests: prepare common test infrastructure for CLI args
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-12 13:53:55 +00:00
Philipp Schuster
12493db144 ch-remote: move Args and Commands creation to function
This enables to sort them alphabetically in a next step, similar
to #6988 / c37c639f3f.

[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/6988

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-12 13:53:55 +00:00
Jinrong Liang
f151fdb16f vmm: config: Add tests for check block serial length
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
2025-06-12 13:51:52 +00:00
Jinrong Liang
bb6ca56fb0 vmm: config: Add DiskConfig check for device serial length
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
2025-06-12 13:51:52 +00:00
dependabot[bot]
a336533389 build: Bump actions/setup-python from 1 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 1 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v1...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 00:17:53 +00:00
dependabot[bot]
c4b6ed1077 build: Bump getrandom from 0.3.1 to 0.3.3
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.3.1 to 0.3.3.
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.1...v0.3.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 00:01:56 +00:00
dependabot[bot]
3e8dda4e7d build: Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-11 00:57:58 +00:00
dependabot[bot]
e9edb2e51c build: Bump adler2 from 2.0.0 to 2.0.1
Bumps [adler2](https://github.com/oyvindln/adler2) from 2.0.0 to 2.0.1.
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 23:48:15 +00:00
dependabot[bot]
0798effcc6 build: Bump async-io from 2.3.3 to 2.4.1
Bumps [async-io](https://github.com/smol-rs/async-io) from 2.3.3 to 2.4.1.
- [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.3...v2.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 17:42:39 +00:00
dependabot[bot]
6079791bca build: Bump fsfe/reuse-action from 3 to 5
Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 3 to 5.
- [Release notes](https://github.com/fsfe/reuse-action/releases)
- [Commits](https://github.com/fsfe/reuse-action/compare/v3...v5)

---
updated-dependencies:
- dependency-name: fsfe/reuse-action
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 17:26:50 +00:00
Philipp Schuster
ff2330defe ci: activate dependabot for github-actions
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-10 15:52:12 +00:00
Philipp Schuster
12b72ba3c1 ci: bump typos
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-10 15:52:12 +00:00
dependabot[bot]
92f9e20f57 build: Bump itoa from 1.0.11 to 1.0.15
Bumps [itoa](https://github.com/dtolnay/itoa) from 1.0.11 to 1.0.15.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.11...1.0.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 00:38:46 +00:00
Gauthier Jolly
3d78662498 block: virtio-blk: report IO errors to the guest
Instead of exiting on IO errors, report the errors to the guest with
VIRTIO_BLK_S_IOERR. For example, the guest kernel will log something
similar to this if the nbd behind /dev/vdc is unexpectedly disconnected:

[  166.033957] I/O error, dev vdc, sector 264 op 0x1:(WRITE) flags 0x9800 phys_seg 1 prio class 2
[  166.035083] Aborting journal on device vdc-8.
[  166.037307] Buffer I/O error on dev vdc, logical block 9, lost sync page write
[  166.038471] JBD2: I/O error when updating journal superblock for vdc-8.
[...]
[  174.234470] EXT4-fs (vdc): I/O error while writing superblock

In case the rootfs is not located on the affected block device, this
will not crash the guest.

Fixes: #6995

Signed-off-by: Gauthier Jolly <contact@gjolly.fr>
2025-06-09 16:48:07 +00:00
Jinank Jain
2bc8d51a60 misc: Fix missing lifetime syntax clippy warning
This was caught by the nightly compiler during cargo fuzz build.

error: lifetime flowing from input to output with different syntax can be confusing
   --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/hypervisor/src/arch/x86/emulator/mod.rs:493:26
    |
493 |     pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ----------- the lifetime gets resolved as `'_`
    |                          |
    |                          this lifetime flows to the output
    |
    = note: `-D mismatched-lifetime-syntaxes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(mismatched_lifetime_syntaxes)]`
help: one option is to remove the lifetime for references and use the anonymous lifetime for paths
    |
493 |     pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<'_, T> {

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-09 11:19:11 +00:00
Jinank Jain
51002f2bae build: Bump zbus from 4.4.0 to 5.7.1
Along with this also fix some API incompatibilities issues.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-09 11:19:11 +00:00
Nuno Das Neves
59e11f1b0b hypervisor: mshv: fix advance_rip_update_rax() helper
The dirty bit for the GP registers must be set for the hypervisor to
update them.

Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
2025-06-05 20:23:30 +00:00
Jinank Jain
fc01e4cbec fuzz: Update Cargo.lock for fuzz build
It seems like multiple packages inside Cargo.lock are outdated.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-04 17:04:07 +00:00
Jinank Jain
3f8186f627 hypervisor: Fix issues with nightly compilers
cargo fuzz build complaints about some un-used function in the
instruction emultator. Silence the warning by allowing dead code
generation.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-04 17:04:07 +00:00
Jinank Jain
6f56ef9a36 misc: Move zerocopy to workspace dependencies
Since it is used by multiple components at this point, it is better to
move it to workspace level dependency.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-04 17:04:07 +00:00
Philipp Schuster
d6ed74b5b8 tests: fix vCPU test relying on specific Display formatting
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-30 19:07:15 +00:00
dependabot[bot]
7fbe94a227 build: Bump quote from 1.0.36 to 1.0.40
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.36 to 1.0.40.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.36...1.0.40)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 00:37:50 +00:00
dependabot[bot]
4a1809f596 build: Bump glob from 0.3.1 to 0.3.2
Bumps [glob](https://github.com/rust-lang/glob) from 0.3.1 to 0.3.2.
- [Release notes](https://github.com/rust-lang/glob/releases)
- [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/glob/compare/0.3.1...v0.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-28 23:45:19 +00:00
Yi Wang
0a4169801b arch: x86_64: lower the cpuid log level
There are a little many cpuid logs now. When starting a vm with
64 vcpu, we can get more than four thousand INFO messages:

cat vm1.log |grep 'arch/src/x86_64/mod.rs:891' |wc -l
4352

Signed-off-by: Yi Wang <foxywang@tencent.com>
2025-05-28 17:32:22 +00:00
Philipp Schuster
20296e909a misc: streamline thiserror cargo dep
As almost every sub crate depends on thiserror, lets upgrade it to a
workspace dependency.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-28 17:24:34 +00:00
dependabot[bot]
24a6a1805b build: Bump crc-any from 2.4.4 to 2.5.0
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-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-28 00:18:12 +00:00
dependabot[bot]
dd7318e839 build: Bump crossbeam-utils from 0.8.20 to 0.8.21
Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.20 to 0.8.21.
- [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.20...crossbeam-utils-0.8.21)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 00:01:50 +00:00
dependabot[bot]
37444c4bab build: Bump backtrace from 0.3.74 to 0.3.75
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.74 to 0.3.75.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-24 00:30:20 +00:00
Bo Chen
c9a39cf5b5 build: Release v46.0
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-23 18:29:42 +00:00
dependabot[bot]
f6326df68b build: Bump cc from 1.0.99 to 1.2.23
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.99 to 1.2.23.
- [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.2.23)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-22 23:53:39 +00:00
Bo Chen
7571e93a69 vmm: Deprecate SGX support
This commit adds the warning to deprecate the SGX support with the
intention to remove the support from code base in two release cycles.

See: #6960

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-22 17:41:32 +00:00
Philipp Schuster
ab6e1bd2d8 misc: ch-remote: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 15:13:27 +00:00
Philipp Schuster
517ea00bd9 misc: vmm/api: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 15:13:27 +00:00
Philipp Schuster
ea6d5a04fa misc: net_util: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
799336459d misc: performance-metrics: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
f934e142ba misc: rate_limiter: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
0cde3df44a misc: test_infra: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
7585e16f9d misc: option_parser: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
ab575a54b9 misc: devices: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
d2ca7b0e87 misc: arch: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
dd9bce31e8 misc: block: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
dependabot[bot]
a6370b74d9 build: Bump signal-hook from 0.3.17 to 0.3.18
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.17 to 0.3.18.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.17...v0.3.18)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-version: 0.3.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-22 00:34:40 +00:00
Thomas Prescher
d172a5dddb arch: fix extended topology enumeration leaf
When booting a Linux guest in SMP configuration,
the following kernel warning can be observed:

[Firmware Bug]: CPUID leaf 0xb subleaf 1 APIC ID mismatch 1 != 0

The reason is that we announce the presence of the extended topology
leaf, but fail to announce the x2apic ID in EDX.

Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP thomas.prescher@sap.com
2025-05-21 23:30:13 +00:00
Thomas Prescher
d46517559b vmm: don't allow resizing to 0 vCPUs
No sane guest OS will allow hotplugging all cpus.
However, the REST API currently allows specifying
`ch-remote resize --cpus 0`.

On Linux, we can then observe the following error in the kernel log:

processor cpu0: Offline failed.

Subsequent resize commands via ch-remote will then fail with
VcpuPendingRemovedVcpu because the removal of cpu0 was never
successful.

Fix this by disallowing resizing to zero vCPUs.

Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP thomas.prescher@sap.com
2025-05-21 15:28:22 +00:00
Paolo Bonzini
0463f4f156 vmm: use MmapRegion::bitmap() directly
For use in QEMU, I would like GuestMemoryRegion to return a BitmapSlice
instead of a &Bitmap.  This adds some flexibility that QEMU needs in
order to support a single global dirty bitmap that is sliced by the
various GuestMemoryRegions.

However, this removes access to the methods of AtomicBitmap, and in
particular reset() and get_and_reset().  Fortunately, cloud-hypervisor
always uses GuestMemoryMmap, and therefore `region` is known to be a
&GuestRegionMmap.  Dereferencing it returns the MmapRegion to which the
bitmap is attached, thus calling MmapRegion::bitmap(); this has the
same effect as `<GuestRegionMmap as GuestRegion>::bitmap()`, and works
both with or without https://github.com/rust-vmm/vm-memory/pull/324.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-21 13:00:07 +00:00
Philipp Schuster
fff62d9302 misc: vmm: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
5db92f79bf misc: arch: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
06f3049d24 misc: arch/x86_64: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
28e0a95450 misc: virtio-devices: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
a615c809eb misc: vsock: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
a3dcaedf7e misc: vhost_user_net: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
eb0b14f70e misc: vhost_user_block: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
80e66657cc misc: pci: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
fd5cfb75f3 misc: net_util: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
8696bc6604 misc: hypervisor: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
93b599e59e misc: devices: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
01761c2596 misc: block: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
a212343908 misc: arch/riscv64: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
d1a406143d misc: arch/aarch64: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
38380198e1 misc: api_client: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
0e40a50407 misc: option_parser: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
dependabot[bot]
262984f8fc build: Bump miniz_oxide from 0.8.0 to 0.8.8
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.8.0 to 0.8.8.
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.8.0...0.8.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-21 00:11:41 +00:00
Gregory Anders
dce82a34d0 net_util: add support for IPv6 addresses on tap interfaces
Allow tap interfaces to be configured with an IPv6 address. The change
is fairly straightforward: we need to update the API types and CLI
parsing to accept either an IPv6 or IPv4 and then match on the IP
address type when the tap device is configured.

For IPv6 addresses, the netmask (prefix) must be provided at the same
time as the address itself (in the SIOCSIFADDR ioctl). They cannot be
configured separately. So we remove the separate "set_netmask" function
and convert "set_ip_addr" to also accept a netmask. For IPv4 addresses,
the IP address and netmask were already always set together, so this
should have no functional impact for users of IPv4 addresses.

Signed-off-by: Gregory Anders <ganders@cloudflare.com>
2025-05-20 16:41:04 +00:00
dependabot[bot]
1454d39b28 build: Bump igvm_defs from d062818 to 01daa63
Bumps [igvm_defs](https://github.com/microsoft/igvm) from `d062818` to `01daa63`.
- [Release notes](https://github.com/microsoft/igvm/releases)
- [Commits](d062818ffb...01daa631a5)

---
updated-dependencies:
- dependency-name: igvm_defs
  dependency-version: 01daa631a596459cb4de58505881007dd13d4410
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 01:28:42 +00:00
dependabot[bot]
2588fc9e42 build: Bump vfio-bindings from 21d06ce to 3d158a1
Bumps [vfio-bindings](https://github.com/rust-vmm/vfio) from `21d06ce` to `3d158a1`.
- [Release notes](https://github.com/rust-vmm/vfio/releases)
- [Commits](21d06ceb91...3d158a1446)

---
updated-dependencies:
- dependency-name: vfio-bindings
  dependency-version: 3d158a14460cac7ca3c99c2effa0a46880935cb0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-19 23:56:55 +00:00
Philipp Schuster
67793ca375 vmm: improve disk locking error message
This adds guidance on how to resolve the issue.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-19 15:13:01 +01:00
Philipp Schuster
96deca9dc9 vmm: streamline display format for DeviceManagerError
This format is also used elsewhere.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>

On-behalf-of: SAP <philipp.schuster@sap.com>
2025-05-16 11:42:01 +00:00
Philipp Schuster
78b0f68b21 vmm: Error for MemoryManagerError
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>

On-behalf-of: SAP <philipp.schuster@sap.com>
2025-05-16 11:42:01 +00:00
Philipp Schuster
a007b750ff vmm: Error for PciDeviceError and PciRootError
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>

On-behalf-of: SAP <philipp.schuster@sap.com>
2025-05-16 11:42:01 +00:00
Philipp Schuster
b2993fb2fa vmm: Error for vsock::unix::Error
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 11:42:01 +00:00
Philipp Schuster
8d11bf7979 vmm: Error for DeviceManagerError
The DeviceManagerError type is among the types missing the Error trait
so far. To streamline the code and to simplify usage on higher levels
of this error type, this type now implements Display and Error.

As not all variant values are Error yet, `#[source]` is not everywhere
where it could be. This is done in the next commits.

The high level goal is: Enable future work to improve the error output
of cloud hypervisor.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 11:42:01 +00:00
Philipp Schuster
d4718a9bc8 tests: fix parallel rw disk access
The new locking behavior uncovered that unfortunate test situation:
Many tests running in parallel access the same disk image with
rw permissions. Luckily, none of the tests actually writes to
the disk. Therefore, we can set it to readonly=true. In case this
changes, the test needs to be moved to the sequential test module.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
05968f5c2c block: introduce advisory locks for disk image files
# What

This commit introduces file-based advisory locking for the files backing
up the block devices by using the fcntl() syscall with OFD locks. The
per-open-file-descriptor (OFD) locks are more robust than traditional
POSIX locks (F_SETLK) as they are not tied to process IDs and avoid
common issues in multithreaded or multi-fd scenarios [1]. Therefore,
we don't use `std::fs::File::try_lock()`, which is backed by F_SETLKW.

The locking mechanism is aware of the `readonly` property and allows
`n` readers or `1` writer (exclusive mode).

As the locks are advisory, multiple cloud-hypervisor processes can
prevent themselves from writing to the same file. However, this is not
a system-wide file-system level locking mechanism preventing to open()
a file.

The introduced new locking mechanism does not cover vhost-user devices.

# Why

To prevent misconfiguration and improve safety, it is good practice to
protect disk image files with a locking mechanism. Experience and common
best practices suggest that advisory locks are preferable over mandatory
locks due to better compatibility and fewer pitfalls (in fs space).

The introduced functionality is aligned with the approach taken by
QEMU [0], and is also recommended in [1].

# Implementation Details

We need to ensure that not only normal operation keeps working but also
state save/resume and live-migration. Especially for live migration,
it is crucial that the sender VMM releases the locks when the VM stops
so the receiver VMM can acquire them right after that.

Therefore, the locking and releasing happen directly on the block
device struct. The device manager knows all block devices and can
forward requests to these types.

Last but not least, this commit uses on explicit lock acquiring
but implicit lock releasing (FD close). It only explicitly releases
the locks where this integrates more smoothly into the existing
code.

# Testing

I tested
- normal operation
- state save/resume,
- device hot plugging,
- and live-migration
with read/shared and write/exclusive locks.

One can use the `fcntl-tool` to test if locks are actually acquired
or released [2].

# Links

[0] 825b96dbce/util/osdep.c (L266)
[1] https://apenwarr.ca/log/20101213
[2] https://crates.io/crates/fcntl-tool

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
71a36e0c69 block: add fcntl module for locking
This is a prerequisite for the next steps.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
2da5e10689 block: bind FD lifetime of DiskFile
As we can't use BorrowedFd, we should at least create a similar
safe alternative.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
a647d7863c block: enable to get a raw FD of each block device's DiskFile
This is a prerequisite for the next steps.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
a23d4b7cf2 block: fixing typo, increase clarity
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
f3209e4f78 devices: silence IRQ debug!() spam
This simplifies debugging of running VMs.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Bo Chen
596d6453c5 vmm: Allow 'VFIO_IOMMU_MAP_DMA' ioctl from the vcpu worker thread
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 20:11:48 +00:00
Bo Chen
1307d31ede pci: vfio: Report more information with failed vfio_dma_unmap
Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 20:11:48 +00:00
Bo Chen
2f21827430 pci: vfio: Update IOMMU mappings of MMIO regions with BAR reprogram
To support PCIe P2P between VFIO devices, we populate IOMMU mappings for
the non-emulated MMIO regions of all VFIO devices via
`VFIO_IOMMU_MAP_DMA` (f0c1f8d), but the patch did not properly update
the IOMMU mappings with BAR reprogramming.

Fixes: #7027

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 20:11:48 +00:00
Bo Chen
8da7c13e26 pci: Handle pending BAR reprogramming for VFIO devices properly
The way how we handle PCI configuration space for vfio and vfio-user
devices are different from the rest of PCI devices. Besides accesses to
BAR registers (trapped to access the shadowing PCI config space we
maintained), accesses to other registers (including the COMMAND
register) are handled directly by the underline vfio or vfio-user
device.

This patch adds the proper handling of pending BAR reprogramming for
vfio and vfio-user devices.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 17:35:44 +00:00
Bo Chen
aaf86ef209 pci: Reprogram device BAR when its MSE bit is set
The Memory Space Enable (MSE) bit from the COMMAND register in the
PCI configuration space controls whether a PCI device responds to memory
space accesses, e.g. read and write cycles to the device MMIO regions
defined by its BARs. The MSE bit is used by the device drivers to ensure
the correctness of BAR reprogramming. A common workflow is, the driver
first clears the MSE bit, then writes new values to the BAR registers,
and finally set the MSE bit to finish the BAR reprogramming.

This patch changes how we handle BAR reprogramming for all PCI
devices (e.g. virtio-pci, vfio, vfio-user, etc.), so that we follow the
same convention, e.g. moving PCI BARs when its MSE bit is set.

Note that some device drivers (such as edk2) only clear and set MSE once
while reprogramming multiple BARs of a single device. To support such
behavior, this patch adds support for multiple pending BAR reprogramming.

See: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7027#issuecomment-2853642959

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 17:35:44 +00:00
Bo Chen
59f98a2edc pci: configuration: Log BAR reprogramming correctly
Use the right bar index and bar address maintained internally by the
VMM when logging BAR reprogramming.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 15:04:01 +00:00
Bo Chen
cb52cf91df pci: Keep detect_bar_reprogramming internal to PciConfiguration
A BAR reprogramming of a PCI device will only happen when the (guest)
kernel write to its PCI config space, e.g. the detection of bar
reprogramming (`detect_bar_repgraomming()`) can be embedded to the PCI
config space write (`write_config_register()`). It simplifies APIs
exposed by the `struct PciConfiguration` and `trait PciDevice`. It also
prepares for easier handling of pending bar reprogramming when the MSE
bit of the COMMAND register is not enabled at the time of changing BAR
registers.

See: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7027#issuecomment-2853642959

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-15 15:04:01 +00:00
Muminul Islam
5814193722 build: Bump mshv crates from 0.5.0 to 0.5.1
This release has critical bug fixes IOCTL changes.
No API changes.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-05-15 06:39:22 +00:00
Bo Chen
10ee003d66 misc: Fix beta clippy issues
Fixing the following clippy issue using `cargo clippy --fix`:

error: variables can be used directly in the `format!` string
  --> build.rs:25:27
   |
25 |         version.push_str(&format!("-{}", extra_version));
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-14 03:44:12 +00:00
Jinank Jain
8f402687ce hypervisor: mshv: Add missing implementation
Currently a lot of functions are stubbed out with unimplemented feature
tag. Add the missing implementation to successfully boot ARM64 guests on
MSHV.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
f72f16ee50 arch: Fix incorrect FDT generation
Num SPI and Base SPI nodes should be added before the end node to be
included in the device tree generation.

Fixes: eac44e6 (arch: Extend FDT for GICv2M device for ARM64 on MSHV)
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
034aa514d7 vmm: Unify address space allocation
It seems like address allocation has been spread into different files
and different location for x86 vs ARM. This makes it hard to follow the
code. Thus, unify it a single location which satisfies all the
requirement.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
4e48f429eb vmm: Unify loading of payload for IGVM and non-IGVM
It just simplifies code and improves the code read-ability without much
affecting the boot performance.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
50b0493371 vmm: Move vm init after interrupt controller init
This will satisfy the requirement of MSHV i.e., setting the GICD base
address before initializing the VM.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
df418a2153 vmm: Split device creation from interrupt controller creation
For MSHV guests, we would need interrupt controller to be initialized
before the VM gets initialized. This is because we are registering the
base address of GIC distributor with MSHV as part of interrupt
controller initialization workflow. And MSHV mandates that this property
is set before we initialize the VM.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
a072b9a356 hypervisor: Set additional partition property for MSHV guest
For ARM64 guests we need to set three important partition property:

1) PPI interrupt ID for timer interrupt
2) PPI interrupt ID for PMU interrupts.
3) Hiding LPI support from the guest because MSHV does emulate ITS for
   the guest.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
691fe0ca68 hypervisor: arch: Move PMU IRQ definition from arch to hypervisor crate
Since this would be used in other places inside the hypervisor and
hypervisor crate cannot take a dependency on arch crate, as that creates
cyclic dependency.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Jinank Jain
aaa3a114dd arch: hypervisor: Define PPI constants for ARM arch timer
Currently PPI interrupt ID are hardcoded as numbers, it would be ideal
to define them as constants and could be reused in other parts of the
hypervisor crate.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-09 16:06:12 +00:00
Philipp Schuster
77e042237d ci: improve gitlint (max line length in body with exceptions)
Follow-up of 5aa1540c5d but way more
mature. We now use custom gitlint rules written in Python to better
handle the max line length, with respect to a few valid exceptions.
Recognizing code blocks or compiler output, as discussed, is not
trivial and hard to get right for all corner-cases. Therefore, this
commit is a pragmatic way forward. The CI job should be kept optional.

Allowed exceptions for the 72 line length limit are now:

1. links in the following three common patterns:
https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links
[0] https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links
[0]: https://example.com/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links/very-long-links

2. code blocks (anything between the three backticks)

```
let x = "very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_very_long_"
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-09 14:50:23 +01:00
Jinank Jain
f16d45e86e build: Bump mshv crates from 0.4.0 to 0.5.0
Along with also bump the vfio-bindings crates to use the latest
mshv-bindings.

There is a breaking change in the new mshv crate which requires an
additional step to initialize vm after creating it.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-05 17:42:30 +00:00
Jinank Jain
3eb6b69dd2 hypervisor: Extend interrupt handling for legacy IRQ
On x86 MSHV guests only used to support MSI based interrupts via IOAPIC
but ARM64 guests uses legacy interrupt for its functioning. Thus, extend
the logic to create routing entry to support legacy interrupts for ARM64
guests on MSHV.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-05 10:44:16 +00:00
Jinank Jain
fa2b5ca12b vmm: hypervisor: Add a new interface to setup GICR for vcpus
For MSHV arm64 guest, there is an in-hypervisor GICv2M emulation and for
that to work, it needs to be enlightened with the base address of GIC
redistributor exposed to guest via FDT.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-05 09:57:21 +00:00
Jinank Jain
eac44e6af0 arch: Extend FDT for GICv2M device for ARM64 on MSHV
GICv2M requires two additional properties to be exposed via FDT:
1) Base SPI number and 2) Total number of SPIs. SPIs in general starts
from 32 and goes upto 1019. But currently we are limiting the range to
96 as that should be good enough for any normal Linux guest to function.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-05-05 09:05:02 +00:00
abm-77
40055595ff docs: Update riscv docs for developing in QEMU VM
Since there are not a wide availability of RISC-V boards available at
the moment, it is easiest to develop with a QEMU virtual machine. I had
a hard time setting one up, but with the assistance of Ruoqing, I was
able to get one running. These are the steps I took to do so.

Signed-off-by: abm-77 <andrewmiller77@protonmail.com>
2025-05-03 11:11:05 +00:00
Bingxin Li
149c08981b README: Update ubuntu support status
Ubuntu 24.04 LTS (Noble Numbat) is tested against cloud-hypervisor v45.0
release and it is working, document status in README.md.

Signed-off-by: Bingxin Li <bl497@cam.ac.uk>
2025-05-02 07:58:04 +00:00
Jinank Jain
f1f6814774 hypervisor: Implement support for fetching sys regs on MSHV
ARM64 system register constants are not 1:1 mapped to MSHV definition of
those registers so we need a small helper function to translate that
mapping before retrieving those system registers.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-30 06:11:26 +00:00
Jinank Jain
58f71b0c44 hypervisor: arch: Move common regs from arch to hypervisor crate
There are other potential users of these registers definitions in the
hypervisor crate. And hypervisor crate cannot use definitions from arch
crate because it creates cyclic dependency.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-30 06:11:26 +00:00
Fabiano Fidêncio
1968805ba2 api_client: Add TooManyRequests status code
In order to be on-pair with what's we're using from micro-http, let's
also add the proper status code here as well (as it will be used by
`ch-remote`).

Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
2025-04-28 16:24:10 +00:00
Fabiano Fidêncio
d0225fe68f vmm: api: Be more specific on "Still pending remove vcpu" errors
Although the CPU manager gives us a quite descriptive error, on the
application side (the part calling Cloud Hypervisor) we have absolutely
no way to distinguish such error from any other error that may happen
when resizing a VM.

With this in mind, let's be more specific and return a TooManyRequests
(429) error, allowing the caller to have a chance to decide whether they
want to retry the operation or not.

https://datatracker.ietf.org/doc/html/rfc6585#section-4

Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
2025-04-28 16:24:10 +00:00
Fabiano Fidêncio
87007a288f build: Bump micro-http crate
As the coming patches in this series will take advantage of a status
code that was recently added there.

Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
2025-04-28 16:24:10 +00:00
Muminul Islam
f67484a714 hypervisor: mshv: advance_rip_rax after port handle
Call function to advance RIP and RAX after handling the
port.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-26 21:18:22 +00:00
Muminul Islam
3c63779302 hypervisor: mshv: function to advance RIP and RAX
A separate function to advance RIP and RAX based on
register page.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-26 21:18:22 +00:00
Muminul Islam
1c22c4a57b misc: docs: Fix broken link of dpdk.org
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-24 23:23:15 +00:00
Muminul Islam
4af98f4cb2 hypervisor: mshv: get_msr_list return vector instead fam-wrapper
New MSHV version updates the get_msr_list output as
vector instead of fam-wrapper. It avoids unnecessary
conversions.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-24 23:23:15 +00:00
Muminul Islam
c58c686f3e hypervisor: mshv: fix clippy warnings for latest mshv crates
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-24 23:23:15 +00:00
Muminul Islam
9b13d63f28 build: update mshv crates to the latest release
Latest mshv crates contains some IOCTL changes that
enhances VM creation and configures the features in correct
way. Also adds some features that improves register access.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-24 23:23:15 +00:00
Muminul Islam
b5aeb1f63c hypervisor: mshv: use mapped register page for port handling
MSHV allows VMM to map the VP register page into root.
This feature helps VMM to faster process most of the frequent
used registers. This patch uses the VP register page for port
handling in CPU run method.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-04-24 20:37:19 +00:00
Jinank Jain
af2ce3e0cc hypervisor: Basic implementation of setup_regs for MSHV ARM64 guests
As part of this configure the program counter, pstate and X0 registers.
Program counter will point to the start address of the kernel/firmware
in the guest memory. X0 will point to start of the FDT.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-23 07:42:29 +00:00
Jinank Jain
7fd1b9a284 hypervisor: Configure VGIC for MSHV guests
As part of this configuration, two things are being done:

1. Setting up the base address of GIC Distributor
2. Setting up the base address of GIC Interrupt Translator

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-23 07:42:29 +00:00
Jinank Jain
e69acd1dc3 hypervisor: Refactor common PSTATE register definition
Initial PSTATE value would be same for both KVM and MSHV. Thus, move it
to common register definition pool.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-23 07:42:29 +00:00
Julian Stecklina
de764456ce pci: reduce visibility of VfioCommon internals
There are a lot of internal functions that are not and probably should
not be called from other places.

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2025-04-18 18:25:37 +00:00
Julian Stecklina
0095556847 pci: gracefully handle devices that return 0xff as a capability pointer
If a device returns 0xff as a capability pointer bad things happen.
The code before the previous commits would crash in debug builds due
to integer overflow. With the two lowest bits masked out, it sends the
code into an endless loop.

Be more robust by at least handling the case where the capability
appears to point to itself.

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2025-04-18 18:25:37 +00:00
Julian Stecklina
a0065452d8 pci: mask out lower 2 bits in capability list pointers
The PCI standard mandates that the lower bits of the capability
pointer are masked out before using the pointer. See PCI Local Bus
Specification 3.0 Chapter 6.7 "Capabilities List".

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2025-04-18 18:25:37 +00:00
Julian Stecklina
56ca26e72c pci: only parse capabilities if the device claims to have some
Currently, the code tries to follow the PCI capabilities list in
offset 0x34 in the config space regardless of whether the status
registers says this is valid. Fix by adding the appropriate check.

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2025-04-18 18:25:37 +00:00
Julian Stecklina
21b9806cad ci: Exclude osdev.org from link check
OSDev has cranked up its bot protection. The following link works for
me locally after clicking the "I'm a human" button. I guess the CI
fails this check...

Without this exception the CI fails the link check stage:

* [403] [https://wiki.osdev.org/IOAPIC](https://wiki.osdev.org/IOAPIC) | Network error: Forbidden

Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
2025-04-18 18:25:37 +00:00
Jinank Jain
d374101f38 hypervisor: Use instruction emulator to handle unmapped gpa
Use the context from Unmapped Gpa exit from the hypervisor to initialize
the MshvEmulatorContext and later call the emulator to decode the
instruction.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-17 13:11:23 +00:00
Jinank Jain
461e31e6d8 hypervisor: Instruction emulator for ARM64 guest on MSHV
Currently it would be using the syndrome register for instruction
decoding which is what KVM has been using in-kernel to decode
instructions for ARM64 guests. In future, it could be extended with an
actual instruction emulator if required. But most Linux guests works
well with the instruction decoder using syndrome register.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-17 13:11:23 +00:00
Jinank Jain
d22e7e2638 hypervisor: Add definition for parsing EsrEl2 register
This helps in implementing an instruction decoder for MSVH which does
not support in-kernel instruction decoding like KVM.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-17 13:11:23 +00:00
Jinank Jain
960d702255 hypervisor: Enable MSHV compilation on ARM64
Along with it also enable clippy tests on MSHV aarch64 builds.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-16 03:36:12 +00:00
Jinank Jain
1105243aca vmm: Guard KVM specific unit test with feature guard
Some tests are specifically designed for KVM hypervisor platform. Thus,
guard them using appropriate feature flags.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-16 03:36:12 +00:00
Jinank Jain
317f8002d7 hypervisor: Silence compiler warning for unused variables
There are a bunch of unused variables as of now on the MSHV side and
compiler warns about them. Thus, mark them as unused for the time being.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-16 03:36:12 +00:00
dependabot[bot]
278b57ba49 build: Bump equivalent from 1.0.1 to 1.0.2
Bumps [equivalent](https://github.com/indexmap-rs/equivalent) from 1.0.1 to 1.0.2.
- [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 23:57:05 +00:00
Jinank Jain
d7f87425cd build: Bump mshv crates from 0.3.3 to 0.3.5
Latest mshv crates contains some binding changes required for supporting
ARM64 guests on MSHV.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-15 07:23:44 +00:00
dependabot[bot]
573868c035 build: Bump bitflags from 2.6.0 to 2.9.0
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.6.0 to 2.9.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.6.0...2.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 00:35:22 +00:00
Jinank Jain
2798286278 hypervisor: Add GICv2M support for MSHV ARM64 guest
MSHV does not emulate a GICv3-ITS for guests to support MSI interrupts,
instead it exposes a GICv2m device. Currently adding a skeleton code
which would be modified later on with complete implementation.

With this we can start compiling cloud-hypervisor for MSHV on ARM64.
This will make sure that we don't regress in future in terms of basic
compilation test.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-14 16:33:10 +00:00
Ruoqing He
bcc314eb8b build: Manually bump igvm crates to d062818
`zerocopy` is bumped to 0.8.x after 0.3.4 of igvm crates, bump to rev
d062818 to capture `zerocopy` upgrade, but we should bump to 0.3.5
later.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-04-13 08:06:11 +00:00
Ruoqing He
af28569611 build: Bump zerocopy and acpi_tables
Manually bump zerocopy to 0.8.24 since our dependabot could not perform
the upgrade properly.

Manually bump acpi_tabls as well since it's depending on zerocopy.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-04-13 08:06:11 +00:00
Rob Bradford
1a5dcc5e70 build: Clarify that MSRV bump is an OR of potential reasons
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-04-13 07:39:00 +00:00
Rob Bradford
29b089296d tests: Move test_virtio_pmem_persist_writes to sequential group
This test has been generating a flaky OOM situation when run in the
parallel group.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2025-04-13 07:38:42 +00:00
Ruoqing He
6e4bf84383 hypervisor: Fix clippy empty_line_after_doc_comments
Fix clippy warning empty_line_after_doc_comments reported by rustc
1.83.0 (90b35a623 2024-11-26).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-04-12 18:31:02 +01:00
Ruoqing He
226ecf47bb build: Bump MSRV to 1.83.0
The dependency `bitfield-struct` 0.10.x of `igvm` 0.3.5 requires MSRV
1.83.0, bump to catch up.

Update image to 20250412-0 because MSRV in Dockerfile is updated.

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-04-12 18:31:02 +01:00
Bo Chen
0e3733e938 vmm: openapi: Remove path as required for DiskConfig
This aligns with our CLI syntax. The correctness of `DiskConfig` will be
ensured via `VmConfig::validate()`, e.g. `path` and `socket` are
mutually exclusive.

Fixes: #7016

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-04-09 16:03:12 +00:00
Jinank Jain
f811e36443 hypervisor: Add support for get/set regs for ARM guest on MSHV
Enable getting and setting registers for ARM64 guests on MSHV.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-03 16:46:23 +00:00
Jinank Jain
a64ba04e78 pci: Fix clippy warning while comparing raw pointers
Use the builtin function instead of using `==` operator.

Warning from the beta compiler:

error: use `std::ptr::eq` when comparing raw pointers
--> pci/src/vfio.rs:1616:24

if host_addr == libc::MAP_FAILED {
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    help: try: `std::ptr::eq(host_addr, libc::MAP_FAILED)`

 = help: for further information visit
 = https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
 = note: `-D clippy::ptr-eq` implied by `-D warnings`
 = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-03 13:11:49 +00:00
Jinank Jain
b686a5bb24 vm-allocator: Fix clippy warning for implicit saturating sub
Use the builtin function to improve the readability of the code.

Warning from beta compiler:

error: manual arithmetic check found
--> vm-allocator/src/address.rs:151:30
|
|let adjust = if alignment > 1 { alignment - 1 } else { 0 };
|             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|             help: replace it with: `alignment.saturating_sub(1)`
|
= help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
= note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
= help: to override `-D warnings` add`#[allow(clippy::implicit_saturating_sub)]`

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-03 13:11:49 +00:00
Jinank Jain
ea4693a091 misc: Fix clippy error from beta compiler
Rust has a new way of constructing other error and clippy complains if
we are still using the older way to construct error message. Thus,
migrate to the new approach suggested by the clippy.

Warning from beta compiler:

error: this can be `std::io::Error::other(_)`
--> block/src/vhdx/mod.rs:142:17
 |
 | /                 std::io::Error::new(
 | |                     std::io::ErrorKind::Other,
 | |                     format!("Failed to update VHDx header: {e}"),
 | |                 )
 | |_________________^
 |
 = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error
help: use `std::io::Error::other`

                 std::io::Error::other(
                     format!("Failed to update VHDx header: {e}"),

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-03 13:11:49 +00:00
Jinank Jain
3698b8e74c build: Centralize serde_json crate to workspace
`serde_json` crate is referenced by multiple components, centralize it
to workspace to better manage this crate.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-02 06:20:54 +00:00
Jinank Jain
6bb33601d0 hypervisor: Avoid leaking KVM GIC state into common GIC state
KVM supports GICv3-ITS emulation and the current GicState is modelled
around the KVM implementation. We should refactor this to accomodate
other hypervisor requirements. For example, MSHV only support GICv2M
emulation for guests for delivering MSI interrupts instead of GICv3-ITS.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

so has been skipped for now.

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

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

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

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

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

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

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

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

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

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

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

And quote from @rbradford:

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

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

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

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

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

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

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

Removed deprecated package `python3-distutils`.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The urls explictly excluded in config file are manually checked.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

@@ -1,18 +1,68 @@
version: 2
updates:
- package-ecosystem: cargo
directories:
- "/"
- "/fuzz"
schedule:
interval: weekly
allow:
- dependency-name: "acpi_tables"
- dependency-name: "kvm-bindings"
- dependency-name: "kvm-ioctls"
- dependency-name: "linux-loader"
- dependency-name: "mshv-bindings"
- dependency-name: "mshv-ioctls"
- dependency-name: "seccompiler"
- dependency-name: "vfio-bindings"
- dependency-name: "vfio-ioctls"
- dependency-name: "vfio_user"
- dependency-name: "vhost"
- dependency-name: "vhost-user-backend"
- dependency-name: "virtio-bindings"
- dependency-name: "virtio-queue"
- dependency-name: "vm-fdt"
- dependency-name: "vm-memory"
- dependency-name: "vmm-sys-util"
groups:
rust-vmm:
patterns:
- "*"
- package-ecosystem: cargo
directories:
- "/"
- "/fuzz"
schedule:
interval: weekly
allow:
- dependency-type: all
ignore:
- dependency-name: "acpi_tables"
- dependency-name: "kvm-bindings"
- dependency-name: "kvm-ioctls"
- dependency-name: "linux-loader"
- dependency-name: "mshv-bindings"
- dependency-name: "mshv-ioctls"
- dependency-name: "seccompiler"
- dependency-name: "vfio-bindings"
- dependency-name: "vfio-ioctls"
- dependency-name: "vfio_user"
- dependency-name: "vhost"
- dependency-name: "vhost-user-backend"
- dependency-name: "virtio-bindings"
- dependency-name: "virtio-queue"
- dependency-name: "vm-fdt"
- dependency-name: "vm-memory"
- dependency-name: "vmm-sys-util"
groups:
non-rust-vmm:
patterns:
- "*"
# Makes it possible to have another config for the same directory.
# https://github.com/dependabot/dependabot-core/issues/1778#issuecomment-1988140219
target-branch: main
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 1
allow:
- dependency-type: direct
- dependency-type: indirect
- package-ecosystem: cargo
directory: "/fuzz"
schedule:
interval: daily
open-pull-requests-limit: 1
allow:
- dependency-type: direct
- dependency-type: indirect
open-pull-requests-limit: 1

View File

@@ -10,7 +10,7 @@ jobs:
name: Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions-rust-lang/audit@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -15,13 +15,13 @@ jobs:
- stable
- beta
- nightly
- "1.77.0"
- "1.88.0"
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
@@ -52,6 +52,12 @@ jobs:
- name: Build (default features + pvmemcontrol)
run: cargo rustc --locked --bin cloud-hypervisor --features "pvmemcontrol" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Build (default features + fw_cfg)
run: cargo rustc --locked --bin cloud-hypervisor --features "fw_cfg" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Build (default features + ivshmem)
run: cargo rustc --locked --bin cloud-hypervisor --features "ivshmem" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Build (mshv)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states

View File

@@ -6,9 +6,9 @@ jobs:
name: DCO Check ("Signed-Off-By")
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Set up Python 3.x
uses: actions/setup-python@v1
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Check DCO

View File

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

View File

@@ -19,7 +19,7 @@ jobs:
RUSTFLAGS: -D warnings
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Install Rust toolchain (${{ matrix.rust }})
uses: dtolnay/rust-toolchain@stable
with:

View File

@@ -18,7 +18,7 @@ jobs:
RUSTFLAGS: -D warnings
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Install Rust toolchain (${{ matrix.rust }})
uses: dtolnay/rust-toolchain@stable
with:

View File

@@ -8,12 +8,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v3
uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Install dependencies

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Lint Dockerfile
uses: hadolint/hadolint-action@master

View File

@@ -13,7 +13,7 @@ jobs:
- name: Fix workspace permissions
run: sudo chown -R runner:runner ${GITHUB_WORKSPACE}
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Run unit tests (musl)

View File

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

View File

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

View File

@@ -16,7 +16,7 @@ jobs:
run: sudo chown -R runner:runner ${GITHUB_WORKSPACE}
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Run VFIO integration tests

View File

@@ -11,7 +11,7 @@ jobs:
steps:
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install Docker

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- name: Code checkout
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install Docker

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

@@ -0,0 +1,45 @@
name: Link Check (lychee)
on: pull_request
jobs:
link_check:
name: Link Check
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v5
with:
# Fetch the entire history so git diff can compare against the base branch
fetch-depth: 0
- name: Get changed files in PR
id: changed-files
uses: tj-actions/changed-files@v47 # Using a dedicated action for robustness
with:
# Compare the HEAD of the PR with the merge-base (where the PR branches off)
base_sha: ${{ github.event.pull_request.base.sha }}
# NEW STEP: Print all changed-files outputs for verification
- name: Verify Changed Files
run: |
echo "--- tj-actions/changed-files Outputs ---"
echo "any_changed: ${{ steps.changed-files.outputs.any_changed }}"
echo "all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}"
echo "added_files: ${{ steps.changed-files.outputs.added_files }}"
echo "modified_files: ${{ steps.changed-files.outputs.modified_files }}"
echo "deleted_files: ${{ steps.changed-files.outputs.deleted_files }}"
echo "renamed_files: ${{ steps.changed-files.outputs.renamed_files }}"
echo "----------------------------------------"
# This will also show if the all_changed_files string is empty or not
if [ -n "${{ steps.changed-files.outputs.all_changed_files }}" ]; then
echo "Detected changes: all_changed_files output is NOT empty."
else
echo "No changes detected: all_changed_files output IS empty."
fi
- name: Link Availability Check (Diff Only)
# MODIFIED: Only run lychee if the 'all_changed_files' output is not an empty string
if: ${{ steps.changed-files.outputs.all_changed_files != '' }}
uses: lycheeverse/lychee-action@master
with:
# Pass the space-separated list of changed files to lychee
args: --verbose --config .lychee.toml ${{ steps.changed-files.outputs.all_changed_files }}
failIfEmpty: false
fail: true

237
.github/workflows/mshv-infra.yaml vendored Normal file
View File

@@ -0,0 +1,237 @@
name: MSHV Infra Setup
on:
workflow_call:
inputs:
ARCH:
description: 'Architecture for the VM'
required: true
type: string
KEY:
description: 'SSH Key Name'
required: true
type: string
OS_DISK_SIZE:
description: 'OS Disk Size in GB'
required: true
type: string
RG:
description: 'Resource Group Name'
required: true
type: string
VM_SKU:
description: 'VM SKU'
required: true
type: string
secrets:
MI_CLIENT_ID:
required: true
RUNNER_RG:
required: true
STORAGE_ACCOUNT_PATHS:
required: true
ARCH_SOURCE_PATH:
required: true
USERNAME:
required: true
outputs:
PRIVATE_IP:
description: 'Private IP of the VM'
value: ${{ jobs.infra-setup.outputs.PRIVATE_IP }}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
infra-setup:
name: ${{ inputs.ARCH }} VM Provision
runs-on: mshv
continue-on-error: true
outputs:
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
steps:
- name: Install & login to AZ CLI
env:
MI_CLIENT_ID: ${{ secrets.MI_CLIENT_ID }}
run: |
set -e
echo "Installing Azure CLI if not already installed"
if ! command -v az &>/dev/null; then
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
else
echo "Azure CLI already installed"
fi
az --version
echo "Logging into Azure CLI using Managed Identity"
az login --identity --client-id ${MI_CLIENT_ID}
- name: Get Location
id: get-location
env:
SKU: ${{ inputs.VM_SKU }}
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
run: |
set -e
# Extract vCPU count from SKU (e.g., "Standard_D2s_v3" => 2)
vcpu=$(echo "$SKU" | sed -n 's/^Standard_[A-Za-z]\+\([0-9]\+\).*/\1/p')
if [[ -z "$vcpu" ]]; then
echo "Cannot extract vCPU count from SKU: $SKU"
exit 1
fi
SUPPORTED_LOCATIONS=$(echo "$STORAGE_ACCOUNT_PATHS" | jq -r 'to_entries[] | .key')
for location in $SUPPORTED_LOCATIONS; do
family=$(az vm list-skus --size "$SKU" --location "$location" --resource-type "virtualMachines" --query '[0].family' -o tsv)
if [[ -z "$family" ]]; then
echo "Cannot determine VM family for SKU: $SKU in $location"
continue
fi
usage=$(az vm list-usage --location "$location" --query "[?name.value=='$family'] | [0]" -o json)
current=$(echo "$usage" | jq -r '.currentValue')
limit=$(echo "$usage" | jq -r '.limit')
if [[ $((limit - current)) -ge $vcpu ]]; then
echo "Sufficient quota found in $location"
echo "location=$location" >> "$GITHUB_OUTPUT"
exit 0
fi
done
echo "No location found with sufficient vCPU quota for SKU: $SKU"
exit 1
- name: Create Resource Group
id: rg-setup
env:
LOCATION: ${{ steps.get-location.outputs.location }}
RG: ${{ inputs.RG }}
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
run: |
set -e
echo "Creating Resource Group: $RG"
# Create the resource group
echo "Creating resource group in location: ${LOCATION}"
az group create --name ${RG} --location ${LOCATION}
echo "Resource group created successfully."
- name: Generate SSH Key
id: generate-ssh-key
env:
KEY: ${{ inputs.KEY }}
run: |
set -e
echo "Generating SSH key: $KEY"
mkdir -p ~/.ssh
ssh-keygen -t rsa -b 4096 -f ~/.ssh/${KEY} -N ""
- name: Create VM
id: vm-setup
env:
KEY: ${{ inputs.KEY }}
LOCATION: ${{ steps.get-location.outputs.location }}
OS_DISK_SIZE: ${{ inputs.OS_DISK_SIZE }}
RG: ${{ inputs.RG }}
RUNNER_RG: ${{ secrets.RUNNER_RG }}
USERNAME: ${{ secrets.USERNAME }}
VM_SKU: ${{ inputs.VM_SKU }}
VM_IMAGE_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_image
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
run: |
set -e
echo "Creating $VM_SKU VM: $VM_NAME"
# Extract subnet ID from the runner VM
echo "Retrieving subnet ID..."
SUBNET_ID=$(az network vnet list --resource-group ${RUNNER_RG} --query "[?contains(location, '${LOCATION}')].{SUBNETS:subnets}" | jq -r ".[0].SUBNETS[0].id")
if [[ -z "${SUBNET_ID}" ]]; then
echo "ERROR: Failed to retrieve Subnet ID."
exit 1
fi
# Extract image ID from the runner VM
echo "Retrieving image ID..."
IMAGE_ID=$(az image show --resource-group ${RUNNER_RG} --name ${VM_IMAGE_NAME} --query "id" -o tsv)
if [[ -z "${IMAGE_ID}" ]]; then
echo "ERROR: Failed to retrieve Image ID."
exit 1
fi
# Create VM
az vm create \
--resource-group ${RG} \
--name ${VM_NAME} \
--subnet ${SUBNET_ID} \
--size ${VM_SKU} \
--location ${LOCATION} \
--image ${IMAGE_ID} \
--os-disk-size-gb ${OS_DISK_SIZE} \
--public-ip-sku Standard \
--storage-sku Premium_LRS \
--public-ip-address "" \
--admin-username ${USERNAME} \
--ssh-key-value ~/.ssh/${KEY}.pub \
--security-type Standard \
--output json
echo "VM creation process completed successfully."
- name: Get VM Private IP
id: get-vm-ip
env:
RG: ${{ inputs.RG }}
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
run: |
set -e
echo "Retrieving VM Private IP address..."
# Retrieve VM Private IP address
PRIVATE_IP=$(az vm show -g ${RG} -n ${VM_NAME} -d --query privateIps -o tsv)
if [[ -z "$PRIVATE_IP" ]]; then
echo "ERROR: Failed to retrieve private IP address."
exit 1
fi
echo "PRIVATE_IP=$PRIVATE_IP" >> $GITHUB_OUTPUT
- name: Wait for SSH availability
env:
KEY: ${{ inputs.KEY }}
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
USERNAME: ${{ secrets.USERNAME }}
run: |
echo "Waiting for SSH to be accessible..."
timeout 120 bash -c 'until ssh -o StrictHostKeyChecking=no -i ~/.ssh/${KEY} ${USERNAME}@${PRIVATE_IP} "exit" 2>/dev/null; do sleep 5; done'
echo "VM is accessible!"
- name: Remove Old Host Key
env:
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
run: |
set -e
echo "Removing the old host key"
ssh-keygen -R $PRIVATE_IP
- name: SSH into VM and Install Dependencies
env:
KEY: ${{ inputs.KEY }}
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
USERNAME: ${{ secrets.USERNAME }}
run: |
set -e
ssh -i ~/.ssh/${KEY} -o StrictHostKeyChecking=no ${USERNAME}@${PRIVATE_IP} << EOF
set -e
echo "Logged in successfully."
echo "Installing dependencies..."
sudo tdnf install -y git moby-engine moby-cli clang llvm pkg-config make gcc glibc-devel
echo "Installing Rust..."
curl -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable --profile default -y
export PATH="\$HOME/.cargo/bin:\$PATH"
cargo --version
sudo mkdir -p /etc/docker/
echo '{"default-ulimits":{"nofile":{"Hard":65535,"Name":"nofile","Soft":65535}}}' | sudo tee /etc/docker/daemon.json
sudo systemctl stop docker
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
sudo systemctl start docker
sudo groupadd -f docker
sudo usermod -a -G docker ${USERNAME}
sudo systemctl restart docker
EOF

109
.github/workflows/mshv-integration.yaml vendored Normal file
View File

@@ -0,0 +1,109 @@
name: Cloud Hypervisor Tests (MSHV) (x86_64)
on: [pull_request_target, merge_group]
jobs:
infra-setup:
name: MSHV Infra Setup (x86_64)
uses: ./.github/workflows/mshv-infra.yaml
with:
ARCH: x86_64
KEY: azure_key_${{ github.run_id }}
OS_DISK_SIZE: 512
RG: MSHV-INTEGRATION-${{ github.run_id }}
VM_SKU: Standard_D16s_v5
secrets:
MI_CLIENT_ID: ${{ secrets.MSHV_MI_CLIENT_ID }}
RUNNER_RG: ${{ secrets.MSHV_RUNNER_RG }}
STORAGE_ACCOUNT_PATHS: ${{ secrets.MSHV_STORAGE_ACCOUNT_PATHS }}
ARCH_SOURCE_PATH: ${{ secrets.MSHV_X86_SOURCE_PATH }}
USERNAME: ${{ secrets.MSHV_USERNAME }}
run-tests:
name: Integration Tests (x86_64)
needs: infra-setup
if: ${{ always() && needs.infra-setup.result == 'success' }}
runs-on: mshv
continue-on-error: true
steps:
- name: Run integration tests
timeout-minutes: 60
env:
KEY: azure_key_${{ github.run_id }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO_URL: https://github.com/cloud-hypervisor/cloud-hypervisor.git
REPO_DIR: cloud-hypervisor
PRIVATE_IP: ${{ needs.infra-setup.outputs.PRIVATE_IP }}
RG: MSHV-${{ github.run_id }}
USERNAME: ${{ secrets.MSHV_USERNAME }}
run: |
set -e
echo "Connecting to the VM via SSH..."
ssh -i ~/.ssh/${KEY} -o StrictHostKeyChecking=no ${USERNAME}@${PRIVATE_IP} << EOF
set -e
echo "Logged in successfully."
export PATH="\$HOME/.cargo/bin:\$PATH"
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
git clone --depth 1 "$REPO_URL" "$REPO_DIR"
cd "$REPO_DIR"
git fetch origin pull/${{ github.event.pull_request.number }}/merge
git checkout FETCH_HEAD
else
git clone --depth 1 --single-branch --branch "${{ github.ref_name }}" "$REPO_URL" "$REPO_DIR"
cd "$REPO_DIR"
fi
echo "Loading VDPA kernel modules..."
sudo modprobe vdpa
sudo modprobe vhost_vdpa
sudo modprobe vdpa_sim
sudo modprobe vdpa_sim_blk
sudo modprobe vdpa_sim_net
echo "Creating VDPA devices..."
sudo vdpa dev add name vdpa-blk0 mgmtdev vdpasim_blk
sudo vdpa dev add name vdpa-blk1 mgmtdev vdpasim_blk
sudo vdpa dev add name vdpa-blk2 mgmtdev vdpasim_net
echo "Setting permissions..."
for i in 0 1 2; do
dev="/dev/vhost-vdpa-$i"
if [ -e "$dev" ]; then
sudo chown $USER:$USER "$dev"
sudo chmod 660 "$dev"
else
echo "Warning: Device $dev not found"
fi
done
sudo ./scripts/dev_cli.sh tests --hypervisor mshv --integration
EOF
cleanup:
name: Cleanup
needs: run-tests
if: always()
runs-on: mshv
steps:
- name: Delete RG
env:
RG: MSHV-INTEGRATION-${{ github.run_id }}
run: |
if az group exists --name ${RG}; then
az group delete --name ${RG} --yes --no-wait
else
echo "Resource Group ${RG} does not exist. Skipping deletion."
fi
echo "Cleanup process completed."
- name: Delete SSH Key
env:
KEY: azure_key_${{ github.run_id }}
run: |
if [ -f ~/.ssh/${KEY} ]; then
rm -f ~/.ssh/${KEY} ~/.ssh/${KEY}.pub
echo "SSH key deleted successfully."
else
echo "SSH key does not exist. Skipping deletion."
fi
echo "Cleanup process completed."

View File

@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
container: openapitools/openapi-generator-cli
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Validate OpenAPI
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

View File

@@ -0,0 +1,30 @@
name: Cloud Hypervisor RISC-V 64-bit kvm build Preview
on: [pull_request, merge_group]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Cargo
runs-on: riscv64-qemu-host
strategy:
fail-fast: false
steps:
- name: Code checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install Rust toolchain
run: /opt/scripts/exec-in-qemu.sh rustup default 1.88.0
- name: Build test (kvm)
run: /opt/scripts/exec-in-qemu.sh cargo rustc --locked --no-default-features --features "kvm"
- name: Clippy test (kvm)
run: /opt/scripts/exec-in-qemu.sh cargo clippy --locked --no-default-features --features "kvm"
- name: Check no files were modified
run: test -z "$(git status --porcelain)"

View File

@@ -19,12 +19,12 @@ jobs:
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install Rust toolchain
run: /opt/scripts/exec-in-qemu.sh rustup default 1.77.0
run: /opt/scripts/exec-in-qemu.sh rustup default 1.88.0
- name: Build ${{ matrix.module }} Module (kvm)
run: /opt/scripts/exec-in-qemu.sh cargo rustc --locked -p ${{ matrix.module }} --no-default-features --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states

View File

@@ -29,7 +29,7 @@ jobs:
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
@@ -50,74 +50,112 @@ jobs:
git checkout ${{ github.sha }}
- name: Clippy (kvm)
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features)
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 -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + guest_debug)
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 "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- 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 -W clippy::assertions_on_result_states
- name: Clippy (default features + tracing)
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 "tracing" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (mshv)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (mshv + kvm)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features)
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --tests --examples -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + guest_debug)
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --tests --examples --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + pvmemcontrol)
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --tests --examples --features "pvmemcontrol" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + tracing)
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --tests --examples --features "tracing" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + fw_cfg)
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 "fw_cfg" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (default features + ivshmem)
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --tests --examples --features "ivshmem" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (sev_snp)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (igvm)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Clippy (kvm + tdx)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
uses: houseabsolute/actions-rust-cross@v1
with:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "tdx,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
args: --locked --all --all-targets --no-default-features --tests --examples --features "tdx,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks -W clippy::assertions_on_result_states
- name: Check build did not modify any files
run: test -z "$(git status --porcelain)"
@@ -127,6 +165,6 @@ jobs:
name: Typos / Spellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
# Executes "typos ."
- uses: crate-ci/typos@v1.16.11
- uses: crate-ci/typos@v1.39.0

View File

@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Install musl-gcc
if: contains(matrix.platform.target, 'musl')
run: sudo apt install -y musl-tools
@@ -39,13 +39,13 @@ jobs:
matrix.platform.target == 'x86_64-unknown-linux-gnu'
run: rsync -rv --exclude=.git . ../cloud-hypervisor-${{ github.event.ref }}
- name: Build ${{ matrix.platform.target }}
uses: houseabsolute/actions-rust-cross@v0
uses: houseabsolute/actions-rust-cross@v1
with:
command: build
target: ${{ matrix.platform.target }}
args: ${{ matrix.platform.args }}
strip: true
toolchain: "1.77.0"
toolchain: "1.88.0"
- name: Copy Release Binaries
if: github.event_name == 'create' && github.event.ref_type == 'tag'
shell: bash
@@ -54,7 +54,7 @@ jobs:
cp target/${{ matrix.platform.target }}/release/ch-remote ./${{ matrix.platform.name_ch_remote }}
- name: Upload Release Artifacts
if: github.event_name == 'create' && github.event.ref_type == 'tag'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: Artifacts for ${{ matrix.platform.target }}
path: |
@@ -80,13 +80,13 @@ jobs:
github.event_name == 'create' && github.event.ref_type == 'tag' &&
matrix.platform.target == 'x86_64-unknown-linux-gnu'
id: upload-release-cloud-hypervisor-vendored-sources
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
path: cloud-hypervisor-${{ github.event.ref }}.tar.xz
name: cloud-hypervisor-${{ github.event.ref }}.tar.xz
- name: Create GitHub Release
if: github.event_name == 'create' && github.event.ref_type == 'tag'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
draft: true
files: |

View File

@@ -7,6 +7,6 @@ jobs:
name: REUSE Compliance Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v3
uses: fsfe/reuse-action@v6

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Run the shell script checkers
uses: luizm/action-sh-checker@master
env:

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install build dependencies

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@
/rpm/SOURCES
/.vscode
/vendor
__pycache__

View File

@@ -1,6 +1,7 @@
[general]
extra-path=scripts/gitlint/rules.py
extra-path=scripts/gitlint/rules
regex-style-search=true
ignore=body-max-line-length
[ignore-by-author-name]
regex=dependabot
@@ -10,6 +11,3 @@ ignore=all
[title-max-length]
line-length=72
# default 80
[body-max-line-length]
line-length=72

27
.lychee.toml Normal file
View File

@@ -0,0 +1,27 @@
verbose = "info"
exclude = [
# Availability of links below should be manually verified.
# Page for intel TDX support, returns 403 while querying.
'^https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/overview.html',
# Page for TPM, returns 403 while querying.
'^https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf',
# GitHub user smibarber referenced in `CREDITS.md` no longer exist
'^https://github.com/smibarber',
# OSDev has added bot protection and accesses my result in 403 Forbidden.
'^https://wiki.osdev.org',
# Exclude all pages with $ in the URL since $XXX is a variable
"\\$.*",
# Exclude local files
"file://.*",
]
# Exclude loopback addresses
exclude_loopback = true
max_retries = 3
retry_wait_time = 5

View File

@@ -1,4 +1,4 @@
edition = "2021"
edition = "2024"
group_imports="StdExternalCrate"
imports_granularity="Module"

View File

@@ -7,12 +7,16 @@ extend-exclude = [
]
[default.extend-words]
ba = "ba"
CLASSE = "CLASSE"
conectix = "conectix"
Dake = "Dake"
EXTINT = "EXTINT"
INOUT = "INOUT"
MSIS = "MSIS" # MSIs (Message Signaled Interrupt)
SME = "SME" # Secure Memory Encryption
THR = "THR" # Transmitter Holding Register
TRANSLATER = "TRANSLATER"
ba = "ba"
conectix = "conectix"
liness = "liness"
outout = "outout"

View File

@@ -13,7 +13,7 @@ License](https://opensource.org/licenses/Apache-2.0).
## Coding Style
We follow the [Rust Style](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md)
We follow the [Rust Style](https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/src)
convention and enforce it through the Continuous Integration (CI) process calling into `rustfmt`
for each submitted Pull Request (PR).
@@ -36,7 +36,7 @@ commit you make.
## Certificate of Origin
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://01.org/community/signed-process)
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://web.archive.org/web/20230406041855/https://01.org/community/signed-process)
used by the Linux kernel project.
## Patch format
@@ -79,12 +79,12 @@ you want to merge your changes to `cloud-hypervisor`:
1. Fork the [cloud-hypervisor](https://github.com/cloud-hypervisor/cloud-hypervisor) project
into your github organization.
2. Within your fork, create a branch for your contribution.
3. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
1. Within your fork, create a branch for your contribution.
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
against the main branch of the Cloud Hypervisor repository.
4. To update your pull request amend existing commits whenever applicable and
1. To update your pull request amend existing commits whenever applicable and
then push the new changes to your pull request branch.
5. Once the pull request is approved it can be integrated.
1. Once the pull request is approved it can be integrated.
## Issue tracking
@@ -114,3 +114,13 @@ 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
[commit message](https://help.github.com/articles/closing-issues-via-commit-messages/).
## AI Generated Code
Our policy is to decline any contributions known to contain contents
generated or derived from using Large Language Models (LLMs). This
includes ChatGPT, Gemini, Claude, Copilot and similar tools.
The goal is to avoid ambiguity in license compliance and optimize the
use of limited project resources, especially for code review and
maintenance. This policy can be revisited as LLMs evolve and mature.

1281
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,19 +3,19 @@ authors = ["The Cloud Hypervisor Authors"]
build = "build.rs"
default-run = "cloud-hypervisor"
description = "Open source Virtual Machine Monitor (VMM) that runs on top of KVM & MSHV"
edition = "2021"
edition = "2024"
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
license = "Apache-2.0 AND BSD-3-Clause"
name = "cloud-hypervisor"
version = "44.0.0"
version = "49.0.0"
# Minimum buildable version:
# Keep in sync with version in .github/workflows/build.yaml
# Policy on MSRV (see #4318):
# Can only be bumped by:
# Can only be bumped if satisfying any of the following:
# a.) A dependency requires it,
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
# c.) There is a security issue that is addressed by the toolchain update.
rust-version = "1.77.0"
rust-version = "1.88.0"
[profile.release]
codegen-units = 1
@@ -29,34 +29,34 @@ inherits = "release"
strip = false
[dependencies]
anyhow = "1.0.94"
anyhow = { workspace = true }
api_client = { path = "api_client" }
clap = { version = "4.5.13", features = ["string"] }
dhat = { version = "0.3.3", optional = true }
epoll = "4.3.3"
clap = { workspace = true, features = ["string"] }
dhat = { workspace = true, optional = true }
env_logger = { workspace = true }
epoll = { workspace = true }
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
libc = "0.2.167"
log = { version = "0.4.22", features = ["std"] }
libc = { workspace = true }
log = { workspace = true, features = ["std"] }
option_parser = { path = "option_parser" }
seccompiler = { workspace = true }
serde_json = "1.0.120"
signal-hook = "0.3.17"
thiserror = "2.0.6"
serde_json = { workspace = true }
signal-hook = { workspace = true }
thiserror = { workspace = true }
tpm = { path = "tpm" }
tracer = { path = "tracer" }
vm-memory = { workspace = true }
vmm = { path = "vmm" }
vmm-sys-util = { workspace = true }
zbus = { version = "4.4.0", optional = true }
zbus = { version = "5.7.1", optional = true }
[dev-dependencies]
dirs = "5.0.1"
dirs = { workspace = true }
net_util = { path = "net_util" }
once_cell = "1.20.2"
serde_json = "1.0.120"
serde_json = { workspace = true }
test_infra = { path = "test_infra" }
wait-timeout = "0.2.0"
wait-timeout = { workspace = true }
# Please adjust `vmm::feature_list()` accordingly when changing the
# feature list below
@@ -64,9 +64,11 @@ wait-timeout = "0.2.0"
dbus_api = ["vmm/dbus_api", "zbus"]
default = ["io_uring", "kvm"]
dhat-heap = ["dhat", "vmm/dhat-heap"] # For heap profiling
fw_cfg = ["vmm/fw_cfg"]
guest_debug = ["vmm/guest_debug"]
igvm = ["mshv", "vmm/igvm"]
io_uring = ["vmm/io_uring"]
ivshmem = ["vmm/ivshmem"]
kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"]
pvmemcontrol = ["vmm/pvmemcontrol"]
@@ -100,22 +102,53 @@ members = [
"vm-virtio",
"vmm",
]
package.edition = "2024"
[workspace.dependencies]
# rust-vmm crates
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
kvm-bindings = "0.10.0"
kvm-ioctls = "0.19.1"
linux-loader = "0.13.0"
mshv-bindings = "0.3.2"
mshv-ioctls = "0.3.2"
seccompiler = "0.4.0"
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main" }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
vhost = { git = "https://github.com/rust-vmm/vhost", rev = "d983ae0" }
vhost-user-backend = { git = "https://github.com/rust-vmm/vhost", rev = "d983ae0" }
virtio-bindings = "0.2.4"
virtio-queue = "0.14.0"
vm-fdt = { git = "https://github.com/rust-vmm/vm-fdt", branch = "main" }
kvm-bindings = "0.12.1"
kvm-ioctls = "0.22.1"
linux-loader = "0.13.1"
mshv-bindings = "0.6.0"
mshv-ioctls = "0.6.0"
seccompiler = "0.5.0"
vfio-bindings = { version = "0.6.0", default-features = false }
vfio-ioctls = { version = "0.5.1", default-features = false }
vfio_user = { version = "0.1.1", default-features = false }
vhost = { version = "0.14.0", default-features = false }
vhost-user-backend = { version = "0.20.0", default-features = false }
virtio-bindings = "0.2.6"
virtio-queue = "0.16.0"
vm-fdt = "0.3.0"
vm-memory = "0.16.1"
vmm-sys-util = "0.12.1"
vmm-sys-util = "0.14.0"
# igvm crates
# TODO: bump to 0.3.5 release
igvm = { git = "https://github.com/microsoft/igvm", branch = "main" }
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main" }
# serde crates
serde = "1.0.228"
serde_json = "1.0.145"
serde_with = { version = "3.15.0", default-features = false }
# other crates
anyhow = "1.0.99"
bitflags = "2.9.4"
byteorder = "1.5.0"
cfg-if = "1.0.3"
clap = "4.5.49"
dhat = "0.3.3"
dirs = "6.0.0"
env_logger = "0.11.8"
epoll = "4.4.0"
flume = "0.11.1"
libc = "0.2.177"
log = "0.4.28"
signal-hook = "0.3.18"
thiserror = "2.0.17"
uuid = { version = "1.18.1" }
wait-timeout = "0.2.1"
zerocopy = { version = "0.8.27", default-features = false }

View File

@@ -59,9 +59,13 @@ based on the [Rust VMM](https://github.com/rust-vmm) crates.
### Architectures
Cloud Hypervisor supports the `x86-64` and `AArch64` architectures. There are
minor differences in functionality between the two architectures
(see [#1125](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1125)).
Cloud Hypervisor supports the `x86-64`, `AArch64` and `riscv64`
architectures, with functionality varying across these platforms. The
functionality differences between `x86-64` and `AArch64` are documented
in [#1125](https://github.com/cloud-hypervisor/cloud-hypervisor/issues/1125).
The `riscv64` architecture support is experimental and offers limited
functionality. For more details and instructions, please refer to [riscv
documentation](docs/riscv.md).
### Guest OS
@@ -149,7 +153,7 @@ interface will be enabled as per `network-config` details.
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor
$ ./create-cloud-init.sh
$ ./cloud-hypervisor \
--kernel ./hypervisor-fw \
--firmware ./hypervisor-fw \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
@@ -171,6 +175,18 @@ $ ./cloud-hypervisor \
--console off
```
## Booting: `--firmware` vs `--kernel`
The following scenarios are supported by Cloud Hypervisor to bootstrap a VM, i.e.,
to load a payload/bootitem(s):
- Provide firmware
- Provide kernel \[+ cmdline\]\ [+ initrd\]
Please note that our Cloud Hypervisor firmware (`hypervisor-fw`) has a Xen PVH
boot entry, therefore it can also be booted via the `--kernel` parameter, as
seen in some examples.
### Custom Kernel and Disk Image
#### Building your Kernel
@@ -297,8 +313,9 @@ Further details can be found in the [release documentation](docs/releases.md).
As of 2023-01-03, the following cloud images are supported:
- [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (focal-server-cloudimg-{amd64,arm64}.img)
- [Ubuntu Jammy](https://cloud-images.ubuntu.com/jammy/current/) (jammy-server-cloudimg-{amd64,arm64}.img )
- [Fedora 36](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/) ([Fedora-Cloud-Base-36-1.5.x86_64.raw.xz](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/x86_64/images/) / [Fedora-Cloud-Base-36-1.5.aarch64.raw.xz](https://fedora.mirrorservice.org/fedora/linux/releases/36/Cloud/aarch64/images/))
- [Ubuntu Jammy](https://cloud-images.ubuntu.com/jammy/current/) (jammy-server-cloudimg-{amd64,arm64}.img)
- [Ubuntu Noble](https://cloud-images.ubuntu.com/noble/current/) (noble-server-cloudimg-{amd64,arm64}.img)
- [Fedora 36](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/) ([Fedora-Cloud-Base-36-1.5.x86_64.raw.xz](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/x86_64/images/) / [Fedora-Cloud-Base-36-1.5.aarch64.raw.xz](https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/36/Cloud/aarch64/images/))
Direct kernel boot to userspace should work with a rootfs from most
distributions although you may need to enable exotic filesystem types in the

View File

@@ -1,9 +1,9 @@
[package]
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
edition.workspace = true
name = "api_client"
version = "0.1.0"
[dependencies]
thiserror = "2.0.6"
thiserror = { workspace = true }
vmm-sys-util = { workspace = true }

View File

@@ -11,18 +11,24 @@ use vmm_sys_util::sock_ctrl_msg::ScmSocket;
#[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("Error writing to or reading from HTTP socket")]
Socket(#[source] std::io::Error),
#[error("Error sending file descriptors")]
SocketSendFds(#[source] vmm_sys_util::errno::Error),
#[error("Error parsing HTTP status code")]
StatusCodeParsing(#[source] 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:?}: {1:?}")]
ServerResponse(StatusCode, Option<String>),
#[error("Error parsing HTTP Content-Length field")]
ContentLengthParsing(#[source] std::num::ParseIntError),
#[error("Server responded with error {0:?}: {1:?}")]
ServerResponse(
StatusCode,
// TODO: Move `api` module from `vmm` to dedicated crate and use a common type definition
Option<
String, /* Untyped: Currently Vec<String> of error messages from top to root cause */
>,
),
}
#[derive(Clone, Copy, Debug)]
@@ -32,6 +38,7 @@ pub enum StatusCode {
NoContent,
BadRequest,
NotFound,
TooManyRequests,
InternalServerError,
NotImplemented,
Unknown,
@@ -45,6 +52,7 @@ impl StatusCode {
204 => StatusCode::NoContent,
400 => StatusCode::BadRequest,
404 => StatusCode::NotFound,
429 => StatusCode::TooManyRequests,
500 => StatusCode::InternalServerError,
501 => StatusCode::NotImplemented,
_ => StatusCode::Unknown,
@@ -110,12 +118,11 @@ fn parse_http_response(socket: &mut dyn Read) -> Result<Option<String>, Error> {
}
}
if let Some(body_offset) = body_offset {
if let Some(content_length) = content_length {
if res.len() >= content_length + body_offset {
break;
}
}
if let Some(body_offset) = body_offset
&& let Some(content_length) = content_length
&& res.len() >= content_length + body_offset
{
break;
}
}
let body_string = content_length.and(body_offset.map(|o| String::from(&res[o..])));
@@ -181,8 +188,8 @@ pub fn simple_api_full_command_with_fds<T: Read + Write + ScmSocket>(
request_fds,
)?;
if response.is_some() {
println!("{}", response.unwrap());
if let Some(response) = response {
println!("{response}");
}
Ok(())

View File

@@ -1,27 +1,27 @@
[package]
authors = ["The Chromium OS Authors"]
edition = "2021"
edition.workspace = true
name = "arch"
version = "0.1.0"
[features]
default = []
fw_cfg = []
kvm = ["hypervisor/kvm"]
sev_snp = []
tdx = []
[dependencies]
anyhow = "1.0.94"
byteorder = "1.5.0"
anyhow = { workspace = true }
byteorder = { workspace = true }
hypervisor = { path = "../hypervisor" }
libc = "0.2.167"
libc = { workspace = true }
linux-loader = { workspace = true, features = ["bzimage", "elf", "pe"] }
log = "0.4.22"
serde = { version = "1.0.208", features = ["derive", "rc"] }
thiserror = "2.0.6"
uuid = "1.12.1"
log = { workspace = true }
serde = { workspace = true, features = ["derive", "rc"] }
thiserror = { workspace = true }
uuid = { workspace = true }
vm-memory = { workspace = true, features = ["backend-bitmap", "backend-mmap"] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = { workspace = true, features = ["with-serde"] }
[target.'cfg(any(target_arch = "aarch64", target_arch = "riscv64"))'.dependencies]

View File

@@ -15,14 +15,19 @@ use std::{cmp, fs, result, str};
use byteorder::{BigEndian, ByteOrder};
use hypervisor::arch::aarch64::gic::Vgic;
use hypervisor::arch::aarch64::regs::{
AARCH64_ARCH_TIMER_HYP_IRQ, AARCH64_ARCH_TIMER_PHYS_NONSECURE_IRQ,
AARCH64_ARCH_TIMER_PHYS_SECURE_IRQ, AARCH64_ARCH_TIMER_VIRT_IRQ, AARCH64_PMU_IRQ,
};
use thiserror::Error;
use vm_fdt::{FdtWriter, FdtWriterResult};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryRegion};
use super::super::{DeviceType, GuestMemoryMmap, InitramfsConfig};
use super::layout::{
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
GIC_V2M_COMPATIBLE, GICV2M_SPI_BASE, GICV2M_SPI_NUM, IRQ_BASE, MEM_32BIT_DEVICES_SIZE,
MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START, PCI_HIGH_BASE,
PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
};
use crate::{NumaNodes, PciSpaceInfo};
@@ -59,9 +64,6 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
const IRQ_TYPE_EDGE_RISING: u32 = 1;
const IRQ_TYPE_LEVEL_HI: u32 = 4;
// PMU PPI interrupt number
pub const AARCH64_PMU_IRQ: u32 = 7;
// Keys and Buttons
// System Power Down
const KEY_POWER: u32 = 116;
@@ -80,8 +82,8 @@ pub trait DeviceInfoForFdt {
#[derive(Debug, Error)]
pub enum Error {
/// Failure in writing FDT in memory.
#[error("Failure in writing FDT in memory: {0}")]
WriteFdtToMemory(GuestMemoryError),
#[error("Failure in writing FDT in memory")]
WriteFdtToMemory(#[source] GuestMemoryError),
}
type Result<T> = result::Result<T, Error>;
@@ -109,11 +111,8 @@ pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
let file_path = Path::new(&file_directory);
if !file_path.exists() {
warn!("File: {} does not exist.", file_directory);
0
} else {
info!("File: {} exist.", file_directory);
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
// The content of the file is as simple as a size, like: "32K"
let src = src.trim();
@@ -143,11 +142,8 @@ pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
let file_path = Path::new(&file_directory);
if !file_path.exists() {
warn!("File: {} does not exist.", file_directory);
0
} else {
info!("File: {} exist.", file_directory);
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
src.trim().parse::<u32>().unwrap()
}
@@ -166,11 +162,8 @@ pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
let file_path = Path::new(&file_directory);
if !file_path.exists() {
warn!("File: {} does not exist.", file_directory);
0
} else {
info!("File: {} exist.", file_directory);
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
src.trim().parse::<u32>().unwrap()
}
@@ -194,11 +187,8 @@ pub fn get_cache_shared(cache_level: CacheLevel) -> bool {
let file_path = Path::new(&file_directory);
if !file_path.exists() {
warn!("File: {} does not exist.", file_directory);
result = false;
} else {
info!("File: {} exist.", file_directory);
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
let src = src.trim();
if src.is_empty() {
@@ -217,7 +207,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
guest_mem: &GuestMemoryMmap,
cmdline: &str,
vcpu_mpidr: Vec<u64>,
vcpu_topology: Option<(u8, u8, u8)>,
vcpu_topology: Option<(u16, u16, u16, u16)>,
device_info: &HashMap<(DeviceType, String), T, S>,
gic_device: &Arc<Mutex<dyn Vgic>>,
initrd: &Option<InitramfsConfig>,
@@ -230,8 +220,8 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
let mut fdt = FdtWriter::new().unwrap();
// For an explanation why these nodes were introduced in the blob take a look at
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L845
// Look for "Required nodes and properties".
// the "Device Node Requirements" chapter of the Devicetree Specification.
// https://www.devicetree.org/specifications/
// Header or the root node as per above mentioned documentation.
let root_node = fdt.begin_node("")?;
@@ -279,7 +269,7 @@ pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> R
fn create_cpu_nodes(
fdt: &mut FdtWriter,
vcpu_mpidr: &[u64],
vcpu_topology: Option<(u8, u8, u8)>,
vcpu_topology: Option<(u16, u16, u16, u16)>,
numa_nodes: &NumaNodes,
) -> FdtWriterResult<()> {
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
@@ -288,8 +278,11 @@ fn create_cpu_nodes(
fdt.property_u32("#size-cells", 0x0)?;
let num_cpus = vcpu_mpidr.len();
let (threads_per_core, cores_per_package, packages) = vcpu_topology.unwrap_or((1, 1, 1));
let max_cpus: u32 = (threads_per_core * cores_per_package * packages).into();
let (threads_per_core, cores_per_die, dies_per_package, packages) =
vcpu_topology.unwrap_or((1, 1, 1, 1));
let cores_per_package = cores_per_die * dies_per_package;
let max_cpus: u32 =
threads_per_core as u32 * cores_per_die as u32 * dies_per_package as u32 * packages as u32;
// Add cache info.
// L1 Data Cache Info.
@@ -321,7 +314,6 @@ fn create_cpu_nodes(
if !cache_exist {
warn!("cache sysfs system does not exist.");
} else {
info!("cache sysfs system exists.");
// L1 Data Cache Info.
l1_d_cache_size = get_cache_size(CacheLevel::L1D);
l1_d_cache_line_size = get_cache_coherency_line_size(CacheLevel::L1D);
@@ -369,7 +361,7 @@ fn create_cpu_nodes(
if numa_nodes.len() > 1 {
for numa_node_idx in 0..numa_nodes.len() {
let numa_node = numa_nodes.get(&(numa_node_idx as u32));
if numa_node.unwrap().cpus.contains(&(cpu_id as u8)) {
if numa_node.unwrap().cpus.contains(&(cpu_id as u32)) {
fdt.property_u32("numa-node-id", numa_node_idx as u32)?;
}
}
@@ -422,9 +414,6 @@ fn create_cpu_nodes(
fdt.end_node(l2_cache_node)?;
}
if l2_cache_size != 0 && l2_cache_shared {
warn!("L2 cache shared with other cpus");
}
}
fdt.end_node(cpu_node)?;
@@ -461,7 +450,8 @@ fn create_cpu_nodes(
}
if let Some(topology) = vcpu_topology {
let (threads_per_core, cores_per_package, packages) = topology;
let (threads_per_core, cores_per_die, dies_per_package, packages) = topology;
let cores_per_package = cores_per_die * dies_per_package;
let cpu_map_node = fdt.begin_node("cpu-map")?;
// Create device tree nodes with regard of above mapping.
@@ -585,15 +575,14 @@ fn create_memory_node(
&& (first_region_end <= &mem_32bit_reserved_start))
{
panic!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, ram_start, mem_32bit_reserved_start
"Unexpected first memory region layout: (start: 0x{first_region_start:08x}, end: 0x{first_region_end:08x}).
ram_start: 0x{ram_start:08x}, mem_32bit_reserved_start: 0x{mem_32bit_reserved_start:08x}"
);
}
let mem_size = first_region_end - ram_start;
let mem_reg_prop = [ram_start, mem_size];
let memory_node_name = format!("memory@{:x}", ram_start);
let memory_node_name = format!("memory@{ram_start:x}");
let memory_node = fdt.begin_node(&memory_node_name)?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_prop)?;
@@ -606,14 +595,13 @@ fn create_memory_node(
if second_region_start != &ram_64bit_start {
panic!(
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
second_region_start, ram_64bit_start
"Unexpected second memory region layout: start: 0x{second_region_start:08x}, ram_64bit_start: 0x{ram_64bit_start:08x}"
);
}
let mem_size = second_region_end - ram_64bit_start;
let mem_reg_prop = [ram_64bit_start, mem_size];
let memory_node_name = format!("memory@{:x}", ram_64bit_start);
let memory_node_name = format!("memory@{ram_64bit_start:x}");
let memory_node = fdt.begin_node(&memory_node_name)?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_prop)?;
@@ -670,11 +658,19 @@ fn create_gic_node(fdt: &mut FdtWriter, gic_device: &Arc<Mutex<dyn Vgic>>) -> Fd
if gic_device.lock().unwrap().msi_compatible() {
let msic_node = fdt.begin_node("msic")?;
fdt.property_string("compatible", gic_device.lock().unwrap().msi_compatibility())?;
let msi_compatibility = gic_device.lock().unwrap().msi_compatibility().to_string();
fdt.property_string("compatible", msi_compatibility.as_str())?;
fdt.property_null("msi-controller")?;
fdt.property_u32("phandle", MSI_PHANDLE)?;
let msi_reg_prop = gic_device.lock().unwrap().msi_properties();
fdt.property_array_u64("reg", &msi_reg_prop)?;
if msi_compatibility == GIC_V2M_COMPATIBLE {
fdt.property_u32("arm,msi-base-spi", GICV2M_SPI_BASE)?;
fdt.property_u32("arm,msi-num-spis", GICV2M_SPI_NUM)?;
}
fdt.end_node(msic_node)?;
}
@@ -701,9 +697,14 @@ fn create_clock_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
fn create_timer_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
// See
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/interrupt-controller/arch_timer.txt
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/timer/arm%2Carch_timer.yaml
// These are fixed interrupt numbers for the timer device.
let irqs = [13, 14, 11, 10];
let irqs = [
AARCH64_ARCH_TIMER_PHYS_SECURE_IRQ,
AARCH64_ARCH_TIMER_PHYS_NONSECURE_IRQ,
AARCH64_ARCH_TIMER_VIRT_IRQ,
AARCH64_ARCH_TIMER_HYP_IRQ,
];
let compatible = "arm,armv8-timer";
let mut timer_reg_cells: Vec<u32> = Vec::new();
@@ -838,6 +839,21 @@ fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
Ok(())
}
// https://www.kernel.org/doc/Documentation/devicetree/bindings/arm/fw-cfg.txt
#[cfg(feature = "fw_cfg")]
fn create_fw_cfg_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut FdtWriter,
dev_info: &T,
) -> FdtWriterResult<()> {
// FwCfg node
let fw_cfg_node = fdt.begin_node(&format!("fw-cfg@{:x}", dev_info.addr()))?;
fdt.property("compatible", b"qemu,fw-cfg-mmio\0")?;
fdt.property_array_u64("reg", &[dev_info.addr(), dev_info.length()])?;
fdt.end_node(fw_cfg_node)?;
Ok(())
}
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
fdt: &mut FdtWriter,
dev_info: &HashMap<(DeviceType, String), T, S>,
@@ -853,6 +869,8 @@ fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Buil
DeviceType::Virtio(_) => {
ordered_virtio_device.push(info);
}
#[cfg(feature = "fw_cfg")]
DeviceType::FwCfg => create_fw_cfg_node(fdt, info)?,
}
}
@@ -982,39 +1000,39 @@ fn create_pci_nodes(
fdt.property_array_u32("msi-map", &msi_map)?;
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
if pci_device_info_elem.pci_segment_id == 0 {
if let Some(virtio_iommu_bdf) = virtio_iommu_bdf {
// See kernel document Documentation/devicetree/bindings/pci/pci-iommu.txt
// for 'iommu-map' attribute setting.
let iommu_map = [
0_u32,
VIRTIO_IOMMU_PHANDLE,
0_u32,
virtio_iommu_bdf,
virtio_iommu_bdf + 1,
VIRTIO_IOMMU_PHANDLE,
virtio_iommu_bdf + 1,
0xffff - virtio_iommu_bdf,
];
fdt.property_array_u32("iommu-map", &iommu_map)?;
if pci_device_info_elem.pci_segment_id == 0
&& let Some(virtio_iommu_bdf) = virtio_iommu_bdf
{
// See kernel document Documentation/devicetree/bindings/pci/pci-iommu.txt
// for 'iommu-map' attribute setting.
let iommu_map = [
0_u32,
VIRTIO_IOMMU_PHANDLE,
0_u32,
virtio_iommu_bdf,
virtio_iommu_bdf + 1,
VIRTIO_IOMMU_PHANDLE,
virtio_iommu_bdf + 1,
0xffff - virtio_iommu_bdf,
];
fdt.property_array_u32("iommu-map", &iommu_map)?;
// See kernel document Documentation/devicetree/bindings/virtio/iommu.txt
// for virtio-iommu node settings.
let virtio_iommu_node_name = format!("virtio_iommu@{virtio_iommu_bdf:x}");
let virtio_iommu_node = fdt.begin_node(&virtio_iommu_node_name)?;
fdt.property_u32("#iommu-cells", 1)?;
fdt.property_string("compatible", "virtio,pci-iommu")?;
// See kernel document Documentation/devicetree/bindings/virtio/iommu.txt
// for virtio-iommu node settings.
let virtio_iommu_node_name = format!("virtio_iommu@{virtio_iommu_bdf:x}");
let virtio_iommu_node = fdt.begin_node(&virtio_iommu_node_name)?;
fdt.property_u32("#iommu-cells", 1)?;
fdt.property_string("compatible", "virtio,pci-iommu")?;
// 'reg' is a five-cell address encoded as
// (phys.hi phys.mid phys.lo size.hi size.lo). phys.hi should contain the
// device's BDF as 0b00000000 bbbbbbbb dddddfff 00000000. The other cells
// should be zero.
let reg = [virtio_iommu_bdf << 8, 0_u32, 0_u32, 0_u32, 0_u32];
fdt.property_array_u32("reg", &reg)?;
fdt.property_u32("phandle", VIRTIO_IOMMU_PHANDLE)?;
// 'reg' is a five-cell address encoded as
// (phys.hi phys.mid phys.lo size.hi size.lo). phys.hi should contain the
// device's BDF as 0b00000000 bbbbbbbb dddddfff 00000000. The other cells
// should be zero.
let reg = [virtio_iommu_bdf << 8, 0_u32, 0_u32, 0_u32, 0_u32];
fdt.property_array_u32("reg", &reg)?;
fdt.property_u32("phandle", VIRTIO_IOMMU_PHANDLE)?;
fdt.end_node(virtio_iommu_node)?;
}
fdt.end_node(virtio_iommu_node)?;
}
fdt.end_node(pci_node)?;
@@ -1109,10 +1127,7 @@ fn print_node(node: fdt_parser::node::FdtNode<'_, '_>, n_spaces: usize) {
// - At first, try to convert it to CStr and print,
// - If failed, print it as u32 array.
let value_result = match CStr::from_bytes_with_nul(value) {
Ok(value_cstr) => match value_cstr.to_str() {
Ok(value_str) => Some(value_str),
Err(_e) => None,
},
Ok(value_cstr) => value_cstr.to_str().ok(),
Err(_e) => None,
};

View File

@@ -138,3 +138,12 @@ pub const IRQ_BASE: u32 = 32;
/// Number of supported interrupts
pub const IRQ_NUM: u32 = 256;
/// Base SPI interrupt number for the GICv2M MSI frame
pub const GICV2M_SPI_BASE: u32 = 128;
/// Total number of SPIs for the GICv2M MSI frame
pub const GICV2M_SPI_NUM: u32 = 64;
/// GICv2M compatible string
pub const GIC_V2M_COMPATIBLE: &str = "arm,gic-v2m-frame";

View File

@@ -6,8 +6,6 @@
pub mod fdt;
/// Layout for this aarch64 system.
pub mod layout;
/// Module for system registers definition
pub mod regs;
/// Module for loading UEFI binary.
pub mod uefi;
@@ -16,7 +14,8 @@ use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use hypervisor::arch::aarch64::gic::Vgic;
use log::{log_enabled, Level};
use hypervisor::arch::aarch64::regs::MPIDR_EL1;
use log::{Level, log_enabled};
use thiserror::Error;
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
@@ -33,8 +32,8 @@ pub enum Error {
SetupFdt,
/// Failed to write FDT to memory.
#[error("Failed to write FDT to memory: {0}")]
WriteFdtToMemory(fdt::Error),
#[error("Failed to write FDT to memory")]
WriteFdtToMemory(#[source] fdt::Error),
/// Failed to create a GIC.
#[error("Failed to create a GIC")]
@@ -45,24 +44,18 @@ pub enum Error {
InitramfsAddress,
/// Error configuring the general purpose registers
#[error("Error configuring the general purpose registers: {0}")]
RegsConfiguration(hypervisor::HypervisorCpuError),
#[error("Error configuring the general purpose registers")]
RegsConfiguration(#[source] hypervisor::HypervisorCpuError),
/// Error configuring the MPIDR register
#[error("Error configuring the MPIDR register: {0}")]
VcpuRegMpidr(hypervisor::HypervisorCpuError),
#[error("Error configuring the MPIDR register")]
VcpuRegMpidr(#[source] hypervisor::HypervisorCpuError),
/// Error initializing PMU for vcpu
#[error("Error initializing PMU for vcpu")]
VcpuInitPmu,
}
impl From<Error> for super::Error {
fn from(e: Error) -> super::Error {
super::Error::PlatformSpecific(e)
}
}
#[derive(Debug, Copy, Clone)]
/// Specifies the entry point address where the guest must start
/// executing code.
@@ -73,8 +66,8 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
vcpu: &dyn hypervisor::Vcpu,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> super::Result<u64> {
if let Some((kernel_entry_point, _guest_memory)) = boot_setup {
@@ -86,9 +79,7 @@ pub fn configure_vcpu(
.map_err(Error::RegsConfiguration)?;
}
let mpidr = vcpu
.get_sys_reg(regs::MPIDR_EL1)
.map_err(Error::VcpuRegMpidr)?;
let mpidr = vcpu.get_sys_reg(MPIDR_EL1).map_err(Error::VcpuRegMpidr)?;
Ok(mpidr)
}
@@ -135,7 +126,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
guest_mem: &GuestMemoryMmap,
cmdline: &str,
vcpu_mpidr: Vec<u64>,
vcpu_topology: Option<(u8, u8, u8)>,
vcpu_topology: Option<(u16, u16, u16, u16)>,
device_info: &HashMap<(DeviceType, String), T, S>,
initrd: &Option<super::InitramfsConfig>,
pci_space_info: &[PciSpaceInfo],
@@ -189,7 +180,7 @@ pub fn initramfs_load_addr(
}
}
pub fn get_host_cpu_phys_bits(hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u8 {
pub fn get_host_cpu_phys_bits(hypervisor: &dyn hypervisor::Hypervisor) -> u8 {
let host_cpu_phys_bits = hypervisor.get_host_ipa_limit().try_into().unwrap();
if host_cpu_phys_bits == 0 {
// Host kernel does not support `get_host_ipa_limit`,

View File

@@ -1,43 +0,0 @@
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
// SPDX-License-Identifier: Apache-2.0
// AArch64 system register encoding:
// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
//
// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
// +----------+---+-----+-----+-----+-----+-----+----+
// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
// +----------+---+-----+-----+-----+-----+-----+----+
//
// Notes:
// - L and Rt are reserved as implementation defined fields, ignored.
const SYSREG_HEAD: u32 = 0b1101010100u32 << 22;
const SYSREG_OP0_SHIFT: u32 = 19;
const SYSREG_OP0_MASK: u32 = 0b11u32 << 19;
const SYSREG_OP1_SHIFT: u32 = 16;
const SYSREG_OP1_MASK: u32 = 0b111u32 << 16;
const SYSREG_CRN_SHIFT: u32 = 12;
const SYSREG_CRN_MASK: u32 = 0b1111u32 << 12;
const SYSREG_CRM_SHIFT: u32 = 8;
const SYSREG_CRM_MASK: u32 = 0b1111u32 << 8;
const SYSREG_OP2_SHIFT: u32 = 5;
const SYSREG_OP2_MASK: u32 = 0b111u32 << 5;
/// Define the ID of system registers
#[macro_export]
macro_rules! arm64_sys_reg {
($name: tt, $op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => {
pub const $name: u32 = SYSREG_HEAD
| ((($op0 as u32) << SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK as u32)
| ((($op1 as u32) << SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK as u32)
| ((($crn as u32) << SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK as u32)
| ((($crm as u32) << SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK as u32)
| ((($op2 as u32) << SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK as u32);
};
}
arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
arm64_sys_reg!(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0);
arm64_sys_reg!(TTBR1_EL1, 3, 0, 2, 0, 1);
arm64_sys_reg!(TCR_EL1, 3, 0, 2, 0, 2);

View File

@@ -18,9 +18,6 @@ use std::{fmt, result};
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[cfg(target_arch = "x86_64")]
use crate::x86_64::SgxEpcSection;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
@@ -28,14 +25,14 @@ type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitma
#[derive(Debug, Error)]
pub enum Error {
#[cfg(target_arch = "x86_64")]
#[error("Platform specific error (x86_64): {0:?}")]
PlatformSpecific(x86_64::Error),
#[error("Platform specific error (x86_64)")]
PlatformSpecific(#[from] x86_64::Error),
#[cfg(target_arch = "aarch64")]
#[error("Platform specific error (aarch64): {0:?}")]
PlatformSpecific(aarch64::Error),
#[error("Platform specific error (aarch64)")]
PlatformSpecific(#[from] aarch64::Error),
#[cfg(target_arch = "riscv64")]
#[error("Platform specific error (riscv64): {0:?}")]
PlatformSpecific(riscv64::Error),
#[error("Platform specific error (riscv64)")]
PlatformSpecific(#[from] riscv64::Error),
#[error("The memory map table extends past the end of guest memory")]
MemmapTablePastRamEnd,
#[error("Error writing memory map table to guest memory")]
@@ -46,7 +43,7 @@ pub enum Error {
StartInfoSetup,
#[error("Failed to compute initramfs address")]
InitramfsAddress,
#[error("Error writing module entry to guest memory: {0}")]
#[error("Error writing module entry to guest memory")]
ModlistSetup(#[source] vm_memory::GuestMemoryError),
#[error("RSDP extends past the end of guest memory")]
RsdpPastRamEnd,
@@ -84,9 +81,9 @@ pub mod aarch64;
#[cfg(target_arch = "aarch64")]
pub use aarch64::{
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::IRQ_BASE, uefi, EntryPoint, _NSIG,
_NSIG, EntryPoint, arch_memory_regions, configure_system, configure_vcpu,
fdt::DeviceInfoForFdt, get_host_cpu_phys_bits, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, uefi,
};
/// Module for riscv64 related functionality.
@@ -95,9 +92,9 @@ pub mod riscv64;
#[cfg(target_arch = "riscv64")]
pub use riscv64::{
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::IRQ_BASE, EntryPoint, _NSIG,
_NSIG, EntryPoint, arch_memory_regions, configure_system, configure_vcpu,
fdt::DeviceInfoForFdt, get_host_cpu_phys_bits, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, uefi,
};
#[cfg(target_arch = "x86_64")]
@@ -105,10 +102,9 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use x86_64::{
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry,
EntryPoint, _NSIG,
_NSIG, CpuidConfig, CpuidFeatureEntry, EntryPoint, arch_memory_regions, configure_system,
configure_vcpu, generate_common_cpuid, generate_ram_ranges, get_host_cpu_phys_bits,
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
};
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
@@ -123,12 +119,10 @@ fn pagesize() -> usize {
pub struct NumaNode {
pub memory_regions: Vec<Arc<GuestRegionMmap>>,
pub hotplug_regions: Vec<Arc<GuestRegionMmap>>,
pub cpus: Vec<u8>,
pub cpus: Vec<u32>,
pub pci_segments: Vec<u16>,
pub distances: BTreeMap<u32, u8>,
pub memory_zones: Vec<String>,
#[cfg(target_arch = "x86_64")]
pub sgx_epc_sections: Vec<SgxEpcSection>,
}
pub type NumaNodes = BTreeMap<u32, NumaNode>;
@@ -155,6 +149,9 @@ pub enum DeviceType {
/// Device Type: GPIO.
#[cfg(target_arch = "aarch64")]
Gpio,
/// Device Type: fw_cfg.
#[cfg(feature = "fw_cfg")]
FwCfg,
}
/// Default (smallest) memory page size for the supported architectures.

View File

@@ -54,8 +54,8 @@ pub trait DeviceInfoForFdt {
#[derive(Debug, Error)]
pub enum Error {
/// Failure in writing FDT in memory.
#[error("Failure in writing FDT in memory: {0}")]
WriteFdtToMemory(GuestMemoryError),
#[error("Failure in writing FDT in memory")]
WriteFdtToMemory(#[source] GuestMemoryError),
}
type Result<T> = result::Result<T, Error>;
@@ -119,7 +119,7 @@ fn create_cpu_nodes(fdt: &mut FdtWriter, num_cpus: u32) -> FdtWriterResult<()> {
fdt.property_u32("timebase-frequency", timebase_frequency)?;
for cpu_index in 0..num_cpus {
let cpu = fdt.begin_node(&format!("cpu@{:x}", cpu_index))?;
let cpu = fdt.begin_node(&format!("cpu@{cpu_index:x}"))?;
fdt.property_string("device_type", "cpu")?;
fdt.property_string("compatible", "riscv")?;
fdt.property_string("mmu-type", "sv48")?;
@@ -184,7 +184,7 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> FdtWr
}
let ram_start = super::layout::RAM_START.raw_value();
let memory_node_name = format!("memory@{:x}", ram_start);
let memory_node_name = format!("memory@{ram_start:x}");
let memory_node = fdt.begin_node(&memory_node_name)?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_property)?;
@@ -448,10 +448,7 @@ fn print_node(node: fdt_parser::node::FdtNode<'_, '_>, n_spaces: usize) {
// - At first, try to convert it to CStr and print,
// - If failed, print it as u32 array.
let value_result = match CStr::from_bytes_with_nul(value) {
Ok(value_cstr) => match value_cstr.to_str() {
Ok(value_str) => Some(value_str),
Err(_e) => None,
},
Ok(value_cstr) => value_cstr.to_str().ok(),
Err(_e) => None,
};

View File

@@ -44,16 +44,23 @@
// | |
// | APLICs |
// | |
// 4 MB +---------------------------------------------------------------+
// | UEFI flash |
// 0 GB +---------------------------------------------------------------+
//
//
use vm_memory::GuestAddress;
/// 0x0 ~ 0x40_0000 (4 MiB) is reserved to UEFI
/// UEFI binary size is required less than 3 MiB, reserving 4 MiB is enough.
pub const UEFI_START: GuestAddress = GuestAddress(0);
pub const UEFI_SIZE: u64 = 0x040_0000;
/// AIA related devices
/// See https://elixir.bootlin.com/linux/v6.10/source/arch/riscv/include/uapi/asm/kvm.h
/// 0x0 ~ 0x0400_0000 (64 MiB) resides APLICs
pub const APLIC_START: GuestAddress = GuestAddress(0);
/// 0x40_0000 ~ 0x0400_0000 (64 MiB) resides APLICs
pub const APLIC_START: GuestAddress = GuestAddress(0x40_0000);
pub const APLIC_SIZE: u64 = 0x4000;
/// 0x0400_0000 ~ 0x0800_0000 (64 MiB) resides IMSICs
@@ -91,7 +98,12 @@ pub const CMDLINE_MAX_SIZE: usize = 1024;
pub const FDT_START: GuestAddress = RAM_START;
pub const FDT_MAX_SIZE: u64 = 0x1_0000;
/// Kernel start after FDT
/// Put ACPI table above dtb
pub const ACPI_START: GuestAddress = GuestAddress(RAM_START.0 + FDT_MAX_SIZE);
pub const ACPI_MAX_SIZE: u64 = 0x20_0000;
pub const RSDP_POINTER: GuestAddress = ACPI_START;
/// Kernel start after FDT and ACPI
pub const KERNEL_START: GuestAddress = GuestAddress(RAM_START.0 + FDT_MAX_SIZE);
/// Pci high memory base

View File

@@ -7,19 +7,26 @@
pub mod fdt;
/// Layout for this riscv64 system.
pub mod layout;
/// Module for loading UEFI binary.
pub mod uefi;
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use hypervisor::arch::riscv64::aia::Vaia;
use log::{log_enabled, Level};
use log::{Level, log_enabled};
use thiserror::Error;
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
pub use self::fdt::DeviceInfoForFdt;
use crate::{DeviceType, GuestMemoryMmap, PciSpaceInfo, RegionType};
pub const CLOUDHV_IRQCHIP_NUM_MSIS: u16 = 255;
pub const CLOUDHV_IRQCHIP_NUM_SOURCES: u8 = 96;
pub const CLOUDHV_IRQCHIP_NUM_PRIO_BITS: u8 = 3;
pub const CLOUDHV_IRQCHIP_MAX_GUESTS_BITS: u8 = 3;
pub const CLOUDHV_IRQCHIP_MAX_GUESTS: u8 = (1 << CLOUDHV_IRQCHIP_MAX_GUESTS_BITS) - 1;
pub const _NSIG: i32 = 65;
/// Errors thrown while configuring riscv64 system.
@@ -30,8 +37,8 @@ pub enum Error {
SetupFdt,
/// Failed to write FDT to memory.
#[error("Failed to write FDT to memory: {0}")]
WriteFdtToMemory(fdt::Error),
#[error("Failed to write FDT to memory")]
WriteFdtToMemory(#[source] fdt::Error),
/// Failed to create a AIA.
#[error("Failed to create a AIA")]
@@ -42,14 +49,8 @@ pub enum Error {
InitramfsAddress,
/// Error configuring the general purpose registers
#[error("Error configuring the general purpose registers: {0}")]
RegsConfiguration(hypervisor::HypervisorCpuError),
}
impl From<Error> for super::Error {
fn from(e: Error) -> super::Error {
super::Error::PlatformSpecific(e)
}
#[error("Error configuring the general purpose registers")]
RegsConfiguration(#[source] hypervisor::HypervisorCpuError),
}
#[derive(Debug, Copy, Clone)]
@@ -62,8 +63,8 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
vcpu: &dyn hypervisor::Vcpu,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> super::Result<()> {
if let Some((kernel_entry_point, _guest_memory)) = boot_setup {
@@ -155,7 +156,7 @@ pub fn initramfs_load_addr(
}
}
pub fn get_host_cpu_phys_bits(_hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u8 {
pub fn get_host_cpu_phys_bits(_hypervisor: &dyn hypervisor::Hypervisor) -> u8 {
40
}

50
arch/src/riscv64/uefi.rs Normal file
View File

@@ -0,0 +1,50 @@
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
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, 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>;
pub fn load_uefi<F, M: GuestMemory>(
guest_mem: &M,
guest_addr: GuestAddress,
uefi_image: &mut F,
) -> Result<()>
where
F: Read + Seek + AsFd,
{
let uefi_size = uefi_image
.seek(SeekFrom::End(0))
.map_err(|_| Error::SeekUefiEnd)? as usize;
// edk2 image on virtual platform is smaller than 3M
if uefi_size > 0x300000 {
return Err(Error::UefiTooBig);
}
uefi_image.rewind().map_err(|_| Error::SeekUefiStart)?;
guest_mem
.read_exact_volatile_from(guest_addr, &mut uefi_image.as_fd(), uefi_size)
.map_err(|_| Error::ReadUefiImage)
}

View File

@@ -6,7 +6,6 @@
// found in the LICENSE-BSD-3-Clause file.
use std::result;
use std::sync::Arc;
pub type Result<T> = result::Result<T, hypervisor::HypervisorCpuError>;
@@ -24,7 +23,7 @@ pub fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
///
/// # Arguments
/// * `vcpu` - The VCPU object to configure.
pub fn set_lint(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
pub fn set_lint(vcpu: &dyn hypervisor::Vcpu) -> Result<()> {
let mut klapic = vcpu.get_lapic()?;
let lvt_lint0 = klapic.get_klapic_reg(APIC_LVT0);

View File

@@ -6,16 +6,14 @@
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use std::sync::Arc;
pub mod interrupts;
pub mod layout;
mod mpspec;
mod mptable;
pub mod regs;
use std::collections::BTreeMap;
use std::mem;
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
use hypervisor::arch::x86::{CPUID_FLAG_VALID_INDEX, CpuIdEntry};
use hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError};
use linux_loader::loader::bootparam::{boot_params, setup_header};
use linux_loader::loader::elf::start_info::{
@@ -24,7 +22,7 @@ use linux_loader::loader::elf::start_info::{
use thiserror::Error;
use vm_memory::{
Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryRegion, GuestUsize,
GuestMemoryRegion,
};
use crate::{GuestMemoryMmap, InitramfsConfig, RegionType};
@@ -33,6 +31,10 @@ use std::arch::x86_64;
#[cfg(feature = "tdx")]
pub mod tdx;
// While modern architectures support more than 255 CPUs via x2APIC,
// legacy devices such as mptable support at most 254 CPUs.
pub const MAX_SUPPORTED_CPUS_LEGACY: u32 = 254;
// CPUID feature bits
#[cfg(feature = "kvm")]
const TSC_DEADLINE_TIMER_ECX_BIT: u8 = 24; // tsc deadline timer ecx bit.
@@ -57,6 +59,8 @@ const KVM_FEATURE_ASYNC_PF_VMEXIT_BIT: u8 = 10;
#[cfg(feature = "tdx")]
const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
const KVM_FEATURE_MSI_EXT_DEST_ID: u8 = 15;
pub const _NSIG: i32 = 65;
#[derive(Debug, Copy, Clone)]
@@ -73,55 +77,7 @@ pub struct EntryPoint {
const E820_RAM: u32 = 1;
const E820_RESERVED: u32 = 2;
#[derive(Clone)]
pub struct SgxEpcSection {
start: GuestAddress,
size: GuestUsize,
}
impl SgxEpcSection {
pub fn new(start: GuestAddress, size: GuestUsize) -> Self {
SgxEpcSection { start, size }
}
pub fn start(&self) -> GuestAddress {
self.start
}
pub fn size(&self) -> GuestUsize {
self.size
}
}
#[derive(Clone)]
pub struct SgxEpcRegion {
start: GuestAddress,
size: GuestUsize,
epc_sections: BTreeMap<String, SgxEpcSection>,
}
impl SgxEpcRegion {
pub fn new(start: GuestAddress, size: GuestUsize) -> Self {
SgxEpcRegion {
start,
size,
epc_sections: BTreeMap::new(),
}
}
pub fn start(&self) -> GuestAddress {
self.start
}
pub fn size(&self) -> GuestUsize {
self.size
}
pub fn epc_sections(&self) -> &BTreeMap<String, SgxEpcSection> {
&self.epc_sections
}
pub fn insert(&mut self, id: String, epc_section: SgxEpcSection) {
self.epc_sections.insert(id, epc_section);
}
}
pub struct CpuidConfig {
pub sgx_epc_sections: Option<Vec<SgxEpcSection>>,
pub phys_bits: u8,
pub kvm_hyperv: bool,
#[cfg(feature = "tdx")]
@@ -132,94 +88,76 @@ pub struct CpuidConfig {
#[derive(Debug, Error)]
pub enum Error {
/// Error writing MP table to memory.
#[error("Error writing MP table to memory: {0}")]
MpTableSetup(mptable::Error),
#[error("Error writing MP table to memory")]
MpTableSetup(#[source] mptable::Error),
/// Error configuring the general purpose registers
#[error("Error configuring the general purpose registers: {0}")]
RegsConfiguration(regs::Error),
#[error("Error configuring the general purpose registers")]
RegsConfiguration(#[source] regs::Error),
/// Error configuring the special registers
#[error("Error configuring the special registers: {0}")]
SregsConfiguration(regs::Error),
#[error("Error configuring the special registers")]
SregsConfiguration(#[source] regs::Error),
/// Error configuring the floating point related registers
#[error("Error configuring the floating point related registers: {0}")]
FpuConfiguration(regs::Error),
#[error("Error configuring the floating point related registers")]
FpuConfiguration(#[source] regs::Error),
/// Error configuring the MSR registers
#[error("Error configuring the MSR registers: {0}")]
MsrsConfiguration(regs::Error),
#[error("Error configuring the MSR registers")]
MsrsConfiguration(#[source] regs::Error),
/// Failed to set supported CPUs.
#[error("Failed to set supported CPUs: {0}")]
SetSupportedCpusFailed(anyhow::Error),
#[error("Failed to set supported CPUs")]
SetSupportedCpusFailed(#[source] 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("Cannot set the local interruption due to bad configuration")]
LocalIntConfiguration(#[source] 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("Error setting up SMBIOS table")]
SmbiosSetup(#[source] smbios::Error),
/// Error getting supported CPUID through the hypervisor (kvm/mshv) API
#[error("Error getting supported CPUID through the hypervisor API: {0}")]
CpuidGetSupported(HypervisorError),
#[error("Error getting supported CPUID through the hypervisor API")]
CpuidGetSupported(#[source] 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("Error populating CPUID with KVM HyperV emulation details")]
CpuidKvmHyperV(#[source] 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("Error populating CPUID with CPU identification")]
CpuidIdentification(#[source] 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("Error writing EBDA address")]
EbdaSetup(#[source] vm_memory::GuestMemoryError),
// Error getting CPU TSC frequency
#[error("Error getting CPU TSC frequency: {0}")]
GetTscFrequency(HypervisorCpuError),
#[error("Error getting CPU TSC frequency")]
GetTscFrequency(#[source] 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),
#[error("Error retrieving TDX capabilities through the hypervisor API")]
TdxCapabilities(#[source] HypervisorError),
/// Failed to configure E820 map for bzImage
#[error("Failed to configure E820 map for bzImage")]
E820Configuration,
}
impl From<Error> for super::Error {
fn from(e: Error) -> super::Error {
super::Error::PlatformSpecific(e)
}
}
pub fn get_x2apic_id(cpu_id: u32, topology: Option<(u8, u8, u8)>) -> u32 {
pub fn get_x2apic_id(cpu_id: u32, topology: Option<(u16, u16, u16, u16)>) -> u32 {
if let Some(t) = topology {
let thread_mask_width = u8::BITS - (t.0 - 1).leading_zeros();
let core_mask_width = u8::BITS - (t.1 - 1).leading_zeros();
let die_mask_width = u8::BITS - (t.2 - 1).leading_zeros();
let thread_mask_width = u16::BITS - (t.0 - 1).leading_zeros();
let core_mask_width = u16::BITS - (t.1 - 1).leading_zeros();
let die_mask_width = u16::BITS - (t.2 - 1).leading_zeros();
let thread_id = cpu_id % (t.0 as u32);
let core_id = cpu_id / (t.0 as u32) % (t.1 as u32);
@@ -235,6 +173,13 @@ pub fn get_x2apic_id(cpu_id: u32, topology: Option<(u8, u8, u8)>) -> u32 {
cpu_id
}
pub fn get_max_x2apic_id(topology: (u16, u16, u16, u16)) -> u32 {
get_x2apic_id(
(topology.0 as u32 * topology.1 as u32 * topology.2 as u32 * topology.3 as u32) - 1,
Some(topology),
)
}
#[derive(Copy, Clone, Debug)]
pub enum CpuidReg {
EAX,
@@ -460,7 +405,7 @@ impl CpuidFeatureEntry {
feature_reg: CpuidReg::EDX,
compatible_check: CpuidCompatibleCheck::BitwiseSubset,
},
// KVM CPUID bits: https://www.kernel.org/doc/html/latest/virt/kvm/cpuid.html
// KVM CPUID bits: https://www.kernel.org/doc/html/latest/virt/kvm/x86/cpuid.html
// Leaf 0x4000_0000, EAX/EBX/ECX/EDX, KVM CPUID SIGNATURE
CpuidFeatureEntry {
function: 0x4000_0000,
@@ -579,9 +524,13 @@ impl CpuidFeatureEntry {
error!(
"Detected incompatible CPUID entry: leaf={:#02x} (subleaf={:#02x}), register='{:?}', \
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
);
entry.function,
entry.index,
entry.feature_reg,
entry.compatible_check,
src_vm_feature,
dest_vm_feature
);
compatible = false;
}
@@ -597,7 +546,7 @@ impl CpuidFeatureEntry {
}
pub fn generate_common_cpuid(
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
hypervisor: &dyn hypervisor::Hypervisor,
config: &CpuidConfig,
) -> super::Result<Vec<CpuIdEntry>> {
// SAFETY: cpuid called with valid leaves
@@ -668,10 +617,6 @@ pub fn generate_common_cpuid(
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
if let Some(sgx_epc_sections) = &config.sgx_epc_sections {
update_cpuid_sgx(&mut cpuid, sgx_epc_sections)?;
}
#[cfg(feature = "tdx")]
let tdx_capabilities = if config.tdx {
let caps = hypervisor
@@ -744,15 +689,19 @@ pub fn generate_common_cpuid(
entry.eax = (entry.eax & 0xffff_ff00) | (config.phys_bits as u32 & 0xff);
}
0x4000_0001 => {
// Enable KVM_FEATURE_MSI_EXT_DEST_ID. This allows the guest to target
// device interrupts to cpus with APIC IDs > 254 without interrupt remapping.
entry.eax |= 1 << KVM_FEATURE_MSI_EXT_DEST_ID;
// These features are not supported by TDX
#[cfg(feature = "tdx")]
if config.tdx {
entry.eax &= !(1 << KVM_FEATURE_CLOCKSOURCE_BIT
| 1 << KVM_FEATURE_CLOCKSOURCE2_BIT
| 1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT
| 1 << KVM_FEATURE_ASYNC_PF_BIT
| 1 << KVM_FEATURE_ASYNC_PF_VMEXIT_BIT
| 1 << KVM_FEATURE_STEAL_TIME_BIT)
entry.eax &= !((1 << KVM_FEATURE_CLOCKSOURCE_BIT)
| (1 << KVM_FEATURE_CLOCKSOURCE2_BIT)
| (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)
| (1 << KVM_FEATURE_ASYNC_PF_BIT)
| (1 << KVM_FEATURE_ASYNC_PF_VMEXIT_BIT)
| (1 << KVM_FEATURE_STEAL_TIME_BIT))
}
}
_ => {}
@@ -825,15 +774,15 @@ pub fn generate_common_cpuid(
}
pub fn configure_vcpu(
vcpu: &Arc<dyn hypervisor::Vcpu>,
id: u8,
vcpu: &dyn hypervisor::Vcpu,
id: u32,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
cpuid: Vec<CpuIdEntry>,
kvm_hyperv: bool,
cpu_vendor: CpuVendor,
topology: Option<(u8, u8, u8)>,
topology: (u16, u16, u16, u16),
) -> super::Result<()> {
let x2apic_id = get_x2apic_id(id as u32, topology);
let x2apic_id = get_x2apic_id(id, Some(topology));
// Per vCPU CPUID changes; common are handled via generate_common_cpuid()
let mut cpuid = cpuid;
@@ -855,40 +804,31 @@ pub fn configure_vcpu(
}
assert!(apic_id_patched);
if let Some(t) = topology {
update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id);
}
update_cpuid_topology(
&mut cpuid, topology.0, topology.1, topology.2, topology.3, cpu_vendor, id,
);
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation
if !kvm_hyperv {
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
// Need to check that the TSC doesn't vary with dynamic frequency
// SAFETY: cpuid called with valid leaves
if unsafe { std::arch::x86_64::__cpuid(0x8000_0007) }.edx
& (1u32 << INVARIANT_TSC_EDX_BIT)
> 0
{
CpuidPatch::set_cpuid_reg(
&mut cpuid,
0x4000_0000,
None,
CpuidReg::EAX,
0x4000_0010,
);
cpuid.retain(|c| c.function != 0x4000_0010);
cpuid.push(CpuIdEntry {
function: 0x4000_0010,
eax: tsc_khz,
ebx: 1000000, /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's
* APIC_BUS_CYCLE_NS */
..Default::default()
});
};
}
if !kvm_hyperv && let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
// Need to check that the TSC doesn't vary with dynamic frequency
// SAFETY: cpuid called with valid leaves
if unsafe { std::arch::x86_64::__cpuid(0x8000_0007) }.edx & (1u32 << INVARIANT_TSC_EDX_BIT)
> 0
{
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x4000_0000, None, CpuidReg::EAX, 0x4000_0010);
cpuid.retain(|c| c.function != 0x4000_0010);
cpuid.push(CpuIdEntry {
function: 0x4000_0010,
eax: tsc_khz,
ebx: 1000000, /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's
* APIC_BUS_CYCLE_NS */
..Default::default()
});
};
}
for c in &cpuid {
info!("{}", c);
debug!("{c}");
}
vcpu.set_cpuid2(&cpuid)
@@ -902,7 +842,15 @@ pub fn configure_vcpu(
if let Some((kernel_entry_point, guest_memory)) = boot_setup {
regs::setup_regs(vcpu, kernel_entry_point).map_err(Error::RegsConfiguration)?;
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
regs::setup_sregs(&guest_memory.memory(), vcpu).map_err(Error::SregsConfiguration)?;
// CPUs are required (by Intel sdm spec) to boot in x2apic mode if any
// of the apic IDs is larger than 255. Experimentally, the Linux kernel
// does not recognize the last vCPU if x2apic is not enabled when
// there are 256 vCPUs in a flat hierarchy (i.e. max x2apic ID is 255),
// so we need to enable x2apic in this case as well.
let enable_x2_apic_mode = get_max_x2apic_id(topology) > MAX_SUPPORTED_CPUS_LEGACY;
regs::setup_sregs(&guest_memory.memory(), vcpu, enable_x2_apic_mode)
.map_err(Error::SregsConfiguration)?;
}
interrupts::set_lint(vcpu).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
Ok(())
@@ -952,14 +900,13 @@ pub fn configure_system(
cmdline_addr: GuestAddress,
cmdline_size: usize,
initramfs: &Option<InitramfsConfig>,
_num_cpus: u8,
_num_cpus: u32,
setup_header: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
serial_number: Option<&str>,
uuid: Option<&str>,
oem_strings: Option<&[&str]>,
topology: Option<(u8, u8, u8)>,
topology: Option<(u16, u16, u16, u16)>,
) -> super::Result<()> {
// Write EBDA address to location where ACPICA expects to find it
guest_mem
@@ -975,10 +922,10 @@ pub fn configure_system(
mptable::setup_mptable(offset, guest_mem, _num_cpus, topology).map_err(Error::MpTableSetup)?;
// Check that the RAM is not smaller than the RSDP start address
if let Some(rsdp_addr) = rsdp_addr {
if rsdp_addr.0 > guest_mem.last_addr().0 {
return Err(super::Error::RsdpPastRamEnd);
}
if let Some(rsdp_addr) = rsdp_addr
&& rsdp_addr.0 > guest_mem.last_addr().0
{
return Err(super::Error::RsdpPastRamEnd);
}
match setup_header {
@@ -989,15 +936,8 @@ pub fn configure_system(
initramfs,
hdr,
rsdp_addr,
sgx_epc_region,
),
None => configure_pvh(
guest_mem,
cmdline_addr,
initramfs,
rsdp_addr,
sgx_epc_region,
),
None => configure_pvh(guest_mem, cmdline_addr, initramfs, rsdp_addr),
}
}
@@ -1054,17 +994,15 @@ pub fn generate_ram_ranges(guest_mem: &GuestMemoryMmap) -> super::Result<Vec<Ram
&& (first_region_end <= &mem_32bit_reserved_start))
{
error!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
"Unexpected first memory region layout: (start: 0x{first_region_start:08x}, end: 0x{first_region_end:08x}).
high_ram_start: 0x{high_ram_start:08x}, mem_32bit_reserved_start: 0x{mem_32bit_reserved_start:08x}"
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"first usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
high_ram_start, first_region_end
"first usable physical memory range, start: 0x{high_ram_start:08x}, end: 0x{first_region_end:08x}"
);
(high_ram_start, *first_region_end)
@@ -1089,7 +1027,6 @@ fn configure_pvh(
cmdline_addr: GuestAddress,
initramfs: &Option<InitramfsConfig>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
@@ -1155,15 +1092,6 @@ fn configure_pvh(
E820_RESERVED,
);
if let Some(sgx_epc_region) = sgx_epc_region {
add_memmap_entry(
&mut memmap,
sgx_epc_region.start().raw_value(),
sgx_epc_region.size(),
E820_RESERVED,
);
}
start_info.memmap_entries = memmap.len() as u32;
// Copy the vector with the memmap table to the MEMMAP_START address
@@ -1210,7 +1138,6 @@ fn configure_32bit_entry(
initramfs: &Option<InitramfsConfig>,
setup_hdr: setup_header,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const KERNEL_LOADER_OTHER: u8 = 0xff;
@@ -1266,15 +1193,6 @@ fn configure_32bit_entry(
E820_RESERVED,
)?;
if let Some(sgx_epc_region) = sgx_epc_region {
add_e820_entry(
&mut params,
sgx_epc_region.start().raw_value(),
sgx_epc_region.size(),
E820_RESERVED,
)?;
}
if let Some(rsdp_addr) = rsdp_addr {
params.acpi_rsdp_addr = rsdp_addr.0;
}
@@ -1339,7 +1257,7 @@ pub fn initramfs_load_addr(
Ok(aligned_addr)
}
pub fn get_host_cpu_phys_bits(hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u8 {
pub fn get_host_cpu_phys_bits(hypervisor: &dyn hypervisor::Hypervisor) -> u8 {
// SAFETY: call cpuid with valid leaves
unsafe {
let leaf = x86_64::__cpuid(0x8000_0000);
@@ -1367,21 +1285,24 @@ pub fn get_host_cpu_phys_bits(hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u
fn update_cpuid_topology(
cpuid: &mut Vec<CpuIdEntry>,
threads_per_core: u8,
cores_per_die: u8,
dies_per_package: u8,
threads_per_core: u16,
cores_per_die: u16,
dies_per_package: u16,
packages: u16,
cpu_vendor: CpuVendor,
id: u8,
id: u32,
) {
let x2apic_id = get_x2apic_id(
id as u32,
Some((threads_per_core, cores_per_die, dies_per_package)),
id,
Some((threads_per_core, cores_per_die, dies_per_package, packages)),
);
let thread_width = 8 - (threads_per_core - 1).leading_zeros();
let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width;
let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width;
// Note: the topology defined here is per "package" (~NUMA node).
let thread_width = u16::BITS - (threads_per_core - 1).leading_zeros();
let core_width = u16::BITS - (cores_per_die - 1).leading_zeros() + thread_width;
let die_width = u16::BITS - (dies_per_package - 1).leading_zeros() + core_width;
// The very old way: a flat number of logical CPUs per package: CPUID.1H:EBX[23:16] bits.
let mut cpu_ebx = CpuidPatch::get_cpuid_reg(cpuid, 0x1, None, CpuidReg::EBX).unwrap_or(0);
cpu_ebx |= ((dies_per_package as u32) * (cores_per_die as u32) * (threads_per_core as u32))
& (0xff << 16);
@@ -1391,6 +1312,7 @@ fn update_cpuid_topology(
cpu_edx |= 1 << 28;
CpuidPatch::set_cpuid_reg(cpuid, 0x1, None, CpuidReg::EDX, cpu_edx);
// The legacy way: threads+cores per package.
// CPU Topology leaf 0xb
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg(
@@ -1411,7 +1333,9 @@ fn update_cpuid_topology(
u32::from(dies_per_package * cores_per_die * threads_per_core),
);
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::ECX, 2 << 8);
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::EDX, x2apic_id);
// The modern way: many-level hierarchy (but we here only support four levels).
// CPU Topology leaf 0x1f
CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg(
@@ -1502,57 +1426,6 @@ fn update_cpuid_topology(
}
}
}
// The goal is to update the CPUID sub-leaves to reflect the number of EPC
// sections exposed to the guest.
fn update_cpuid_sgx(
cpuid: &mut Vec<CpuIdEntry>,
epc_sections: &[SgxEpcSection],
) -> Result<(), Error> {
// Something's wrong if there's no EPC section.
if epc_sections.is_empty() {
return Err(Error::NoSgxEpcSection);
}
// We can't go further if the hypervisor does not support SGX feature.
if !CpuidPatch::is_feature_enabled(cpuid, 0x7, 0, CpuidReg::EBX, 2) {
return Err(Error::MissingSgxFeature);
}
// We can't go further if the hypervisor does not support SGX_LC feature.
if !CpuidPatch::is_feature_enabled(cpuid, 0x7, 0, CpuidReg::ECX, 30) {
return Err(Error::MissingSgxLaunchControlFeature);
}
// Get host CPUID for leaf 0x12, subleaf 0x2. This is to retrieve EPC
// properties such as confidentiality and integrity.
// SAFETY: call cpuid with valid leaves
let leaf = unsafe { std::arch::x86_64::__cpuid_count(0x12, 0x2) };
for (i, epc_section) in epc_sections.iter().enumerate() {
let subleaf_idx = i + 2;
let start = epc_section.start().raw_value();
let size = epc_section.size();
let eax = (start & 0xffff_f000) as u32 | 0x1;
let ebx = (start >> 32) as u32;
let ecx = (size & 0xffff_f000) as u32 | (leaf.ecx & 0xf);
let edx = (size >> 32) as u32;
// CPU Topology leaf 0x12
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EAX, eax);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EBX, ebx);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::ECX, ecx);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EDX, edx);
}
// Add one NULL entry to terminate the dynamic list
let subleaf_idx = epc_sections.len() + 2;
// CPU Topology leaf 0x12
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EAX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EBX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::ECX, 0);
CpuidPatch::set_cpuid_reg(cpuid, 0x12, Some(subleaf_idx as u32), CpuidReg::EDX, 0);
Ok(())
}
#[cfg(test)]
mod tests {
use linux_loader::loader::bootparam::boot_e820_entry;
@@ -1583,7 +1456,6 @@ mod tests {
None,
None,
None,
None,
);
config_err.unwrap_err();
@@ -1608,7 +1480,6 @@ mod tests {
None,
None,
None,
None,
)
.unwrap();
@@ -1638,7 +1509,6 @@ mod tests {
None,
None,
None,
None,
)
.unwrap();
@@ -1654,7 +1524,6 @@ mod tests {
None,
None,
None,
None,
)
.unwrap();
}
@@ -1726,22 +1595,27 @@ mod tests {
#[test]
fn test_get_x2apic_id() {
let x2apic_id = get_x2apic_id(0, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(0, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 0);
let x2apic_id = get_x2apic_id(1, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(1, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 1);
let x2apic_id = get_x2apic_id(2, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(2, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 2);
let x2apic_id = get_x2apic_id(6, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(6, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 8);
let x2apic_id = get_x2apic_id(7, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(7, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 9);
let x2apic_id = get_x2apic_id(8, Some((2, 3, 1)));
let x2apic_id = get_x2apic_id(8, Some((2, 3, 1, 1)));
assert_eq!(x2apic_id, 10);
let x2apic_id = get_x2apic_id(257, Some((1, 312, 1, 1)));
assert_eq!(x2apic_id, 257);
assert_eq!(255, get_max_x2apic_id((1, 256, 1, 1)));
}
}

View File

@@ -3,6 +3,8 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
#![allow(non_camel_case_types)]
use vm_memory::ByteValued;
pub const MP_PROCESSOR: ::std::os::raw::c_uint = 0;
pub const MP_BUS: ::std::os::raw::c_uint = 1;
@@ -29,6 +31,13 @@ pub struct mpf_intel {
pub feature5: ::std::os::raw::c_uchar,
}
const _: () = assert!(::core::mem::size_of::<mpf_intel>() == 16);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpf_intel {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_table {
@@ -45,6 +54,19 @@ pub struct mpc_table {
pub reserved: ::std::os::raw::c_uint,
}
const _: () = {
assert!(::core::mem::size_of::<mpc_table>() == 4 + 2 + 1 + 1 + 8 + 12 + 4 + 2 + 2 + 4 + 4);
assert!(::core::mem::size_of::<::std::os::raw::c_uint>() == 4);
assert!(::core::mem::size_of::<::std::os::raw::c_ushort>() == 2);
assert!(::core::mem::size_of::<::std::os::raw::c_uchar>() == 1);
};
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_table {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_cpu {
@@ -57,6 +79,13 @@ pub struct mpc_cpu {
pub reserved: [::std::os::raw::c_uint; 2usize],
}
const _: () = assert!(::core::mem::size_of::<mpc_cpu>() == 20);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_cpu {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_bus {
@@ -65,6 +94,13 @@ pub struct mpc_bus {
pub bustype: [::std::os::raw::c_uchar; 6usize],
}
const _: () = assert!(::core::mem::size_of::<mpc_bus>() == 8);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_bus {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_ioapic {
@@ -75,6 +111,13 @@ pub struct mpc_ioapic {
pub apicaddr: ::std::os::raw::c_uint,
}
const _: () = assert!(::core::mem::size_of::<mpc_ioapic>() == 8);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_ioapic {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_intsrc {
@@ -87,6 +130,13 @@ pub struct mpc_intsrc {
pub dstirq: ::std::os::raw::c_uchar,
}
const _: () = assert!(::core::mem::size_of::<mpc_intsrc>() == 8);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_intsrc {}
pub const MP_IRQ_SOURCE_TYPES_MP_INT: ::std::os::raw::c_uint = 0;
pub const MP_IRQ_SOURCE_TYPES_MP_NMI: ::std::os::raw::c_uint = 1;
pub const MP_IRQ_SOURCE_TYPES_MP_EXT_INT: ::std::os::raw::c_uint = 3;
@@ -103,6 +153,13 @@ pub struct mpc_lintsrc {
pub destapiclint: ::std::os::raw::c_uchar,
}
const _: () = assert!(::core::mem::size_of::<mpc_lintsrc>() == 8);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_lintsrc {}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_oemtable {
@@ -112,3 +169,10 @@ pub struct mpc_oemtable {
pub checksum: ::std::os::raw::c_uchar,
pub mpc: [::std::os::raw::c_uchar; 8usize],
}
const _: () = assert!(::core::mem::size_of::<mpc_oemtable>() == 16);
// SAFETY: all members of this struct are plain integers
// and the sum of their sizes is the size of the struct, so
// padding and reserved values are not possible as there
// would be nowhere for them to exist.
unsafe impl ByteValued for mpc_oemtable {}

View File

@@ -11,9 +11,10 @@ use libc::c_uchar;
use thiserror::Error;
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
use super::MAX_SUPPORTED_CPUS_LEGACY;
use crate::GuestMemoryMmap;
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::{get_x2apic_id, mpspec};
use crate::GuestMemoryMmap;
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `ByteValued`) where:
@@ -59,41 +60,33 @@ pub enum Error {
#[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,
#[error("Failure while zeroing out the memory for the MP table")]
Clear(#[source] GuestMemoryError),
/// Failure to write the MP floating pointer.
#[error("Failure to write the MP floating pointer: {0}")]
WriteMpfIntel(GuestMemoryError),
#[error("Failure to write the MP floating pointer")]
WriteMpfIntel(#[source] GuestMemoryError),
/// Failure to write MP CPU entry.
#[error("Failure to write MP CPU entry: {0}")]
WriteMpcCpu(GuestMemoryError),
#[error("Failure to write MP CPU entry")]
WriteMpcCpu(#[source] GuestMemoryError),
/// Failure to write MP ioapic entry.
#[error("Failure to write MP ioapic entry: {0}")]
WriteMpcIoapic(GuestMemoryError),
#[error("Failure to write MP ioapic entry")]
WriteMpcIoapic(#[source] GuestMemoryError),
/// Failure to write MP bus entry.
#[error("Failure to write MP bus entry: {0}")]
WriteMpcBus(GuestMemoryError),
#[error("Failure to write MP bus entry")]
WriteMpcBus(#[source] GuestMemoryError),
/// Failure to write MP interrupt source entry.
#[error("Failure to write MP interrupt source entry: {0}")]
WriteMpcIntsrc(GuestMemoryError),
#[error("Failure to write MP interrupt source entry")]
WriteMpcIntsrc(#[source] GuestMemoryError),
/// Failure to write MP local interrupt source entry.
#[error("Failure to write MP local interrupt source entry: {0}")]
WriteMpcLintsrc(GuestMemoryError),
#[error("Failure to write MP local interrupt source entry")]
WriteMpcLintsrc(#[source] GuestMemoryError),
/// Failure to write MP table header.
#[error("Failure to write MP table header: {0}")]
WriteMpcTable(GuestMemoryError),
#[error("Failure to write MP table header")]
WriteMpcTable(#[source] GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;
// With APIC/xAPIC, there are only 255 APIC IDs available. And IOAPIC occupies
// one APIC ID, so only 254 CPUs at maximum may be supported. Actually it's
// a large number for FC usecases.
pub const MAX_SUPPORTED_CPUS: u32 = 254;
// Most of these variables are sourced from the Intel MP Spec 1.4.
const SMP_MAGIC_IDENT: &[c_uchar; 4] = b"_MP_";
const MPC_SIGNATURE: &[c_uchar; 4] = b"PCMP";
@@ -106,7 +99,7 @@ const CPU_STEPPING: u32 = 0x600;
const CPU_FEATURE_APIC: u32 = 0x200;
const CPU_FEATURE_FPU: u32 = 0x001;
fn compute_checksum<T: Copy>(v: &T) -> u8 {
fn compute_checksum<T: Copy + ByteValued>(v: &T) -> u8 {
// SAFETY: we are only reading the bytes within the size of the `T` reference `v`.
let v_slice = unsafe { slice::from_raw_parts(v as *const T as *const u8, mem::size_of::<T>()) };
let mut checksum: u8 = 0;
@@ -121,7 +114,7 @@ fn mpf_intel_compute_checksum(v: &mpspec::mpf_intel) -> u8 {
(!checksum).wrapping_add(1)
}
fn compute_mp_size(num_cpus: u8) -> usize {
fn compute_mp_size(num_cpus: u32) -> usize {
mem::size_of::<MpfIntelWrapper>()
+ mem::size_of::<MpcTableWrapper>()
+ mem::size_of::<MpcCpuWrapper>() * (num_cpus as usize)
@@ -135,14 +128,15 @@ fn compute_mp_size(num_cpus: u8) -> usize {
pub fn setup_mptable(
offset: GuestAddress,
mem: &GuestMemoryMmap,
num_cpus: u8,
topology: Option<(u8, u8, u8)>,
num_cpus: u32,
topology: Option<(u16, u16, u16, u16)>,
) -> Result<()> {
if num_cpus > 0 {
let cpu_id_max = num_cpus - 1;
let x2apic_id_max = get_x2apic_id(cpu_id_max.into(), topology);
if x2apic_id_max >= MAX_SUPPORTED_CPUS {
return Err(Error::TooManyCpus);
let x2apic_id_max = get_x2apic_id(cpu_id_max, topology);
if x2apic_id_max >= MAX_SUPPORTED_CPUS_LEGACY {
info!("Skipping mptable creation due to too many CPUs");
return Ok(());
}
}
@@ -157,7 +151,7 @@ pub fn setup_mptable(
}
let mut checksum: u8 = 0;
let ioapicid: u8 = MAX_SUPPORTED_CPUS as u8 + 1;
let ioapicid: u8 = MAX_SUPPORTED_CPUS_LEGACY as u8 + 1;
// The checked_add here ensures the all of the following base_mp.unchecked_add's will be without
// overflow.
@@ -195,7 +189,7 @@ pub fn setup_mptable(
for cpu_id in 0..num_cpus {
let mut mpc_cpu = MpcCpuWrapper(mpspec::mpc_cpu::default());
mpc_cpu.0.type_ = mpspec::MP_PROCESSOR as u8;
mpc_cpu.0.apicid = get_x2apic_id(cpu_id as u32, topology) as u8;
mpc_cpu.0.apicid = get_x2apic_id(cpu_id, topology) as u8;
mpc_cpu.0.apicver = APIC_VERSION;
mpc_cpu.0.cpuflag = mpspec::CPU_ENABLED as u8
| if cpu_id == 0 {
@@ -394,11 +388,11 @@ mod tests {
fn cpu_entry_count() {
let mem = GuestMemoryMmap::from_ranges(&[(
MPTABLE_START,
compute_mp_size(MAX_SUPPORTED_CPUS as u8),
compute_mp_size(MAX_SUPPORTED_CPUS_LEGACY),
)])
.unwrap();
for i in 0..MAX_SUPPORTED_CPUS as u8 {
for i in 0..MAX_SUPPORTED_CPUS_LEGACY {
setup_mptable(MPTABLE_START, &mem, i, None).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
@@ -428,11 +422,9 @@ mod tests {
#[test]
fn cpu_entry_count_max() {
let cpus = MAX_SUPPORTED_CPUS + 1;
let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap();
let cpus = MAX_SUPPORTED_CPUS_LEGACY + 1;
let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus))]).unwrap();
let result = setup_mptable(MPTABLE_START, &mem, cpus as u8, None);
result.unwrap_err();
setup_mptable(MPTABLE_START, &mem, cpus, None).unwrap();
}
}

View File

@@ -6,7 +6,6 @@
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use std::sync::Arc;
use std::{mem, result};
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
@@ -23,41 +22,41 @@ use crate::{EntryPoint, GuestMemoryMmap};
#[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),
#[error("Failed to get SREGs for this CPU")]
GetStatusRegisters(#[source] hypervisor::HypervisorCpuError),
/// Failed to set base registers for this CPU.
#[error("Failed to set base registers for this CPU: {0}")]
SetBaseRegisters(hypervisor::HypervisorCpuError),
#[error("Failed to set base registers for this CPU")]
SetBaseRegisters(#[source] hypervisor::HypervisorCpuError),
/// Failed to configure the FPU.
#[error("Failed to configure the FPU: {0}")]
SetFpuRegisters(hypervisor::HypervisorCpuError),
#[error("Failed to configure the FPU")]
SetFpuRegisters(#[source] hypervisor::HypervisorCpuError),
/// Setting up MSRs failed.
#[error("Setting up MSRs failed: {0}")]
SetModelSpecificRegisters(hypervisor::HypervisorCpuError),
#[error("Setting up MSRs failed")]
SetModelSpecificRegisters(#[source] hypervisor::HypervisorCpuError),
/// Failed to set SREGs for this CPU.
#[error("Failed to set SREGs for this CPU: {0}")]
SetStatusRegisters(hypervisor::HypervisorCpuError),
#[error("Failed to set SREGs for this CPU")]
SetStatusRegisters(#[source] 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),
#[error("Writing the GDT to RAM failed")]
WriteGdt(#[source] GuestMemoryError),
/// Writing the IDT to RAM failed.
#[error("Writing the IDT to RAM failed: {0}")]
WriteIdt(GuestMemoryError),
#[error("Writing the IDT to RAM failed")]
WriteIdt(#[source] GuestMemoryError),
/// Writing PDPTE to RAM failed.
#[error("Writing PDPTE to RAM failed: {0}")]
WritePdpteAddress(GuestMemoryError),
#[error("Writing PDPTE to RAM failed")]
WritePdpteAddress(#[source] GuestMemoryError),
/// Writing PDE to RAM failed.
#[error("Writing PDE to RAM failed: {0}")]
WritePdeAddress(GuestMemoryError),
#[error("Writing PDE to RAM failed")]
WritePdeAddress(#[source] GuestMemoryError),
/// Writing PML4 to RAM failed.
#[error("Writing PML4 to RAM failed: {0}")]
WritePml4Address(GuestMemoryError),
#[error("Writing PML4 to RAM failed")]
WritePml4Address(#[source] GuestMemoryError),
/// Writing PML5 to RAM failed.
#[error("Writing PML5 to RAM failed: {0}")]
WritePml5Address(GuestMemoryError),
#[error("Writing PML5 to RAM failed")]
WritePml5Address(#[source] GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;
@@ -67,7 +66,7 @@ pub type Result<T> = result::Result<T, Error>;
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_fpu(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
pub fn setup_fpu(vcpu: &dyn hypervisor::Vcpu) -> Result<()> {
let fpu: FpuState = FpuState {
fcw: 0x37f,
mxcsr: 0x1f80,
@@ -82,7 +81,7 @@ pub fn setup_fpu(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
pub fn setup_msrs(vcpu: &dyn hypervisor::Vcpu) -> Result<()> {
vcpu.set_msrs(&vcpu.boot_msr_entries())
.map_err(Error::SetModelSpecificRegisters)?;
@@ -95,7 +94,7 @@ pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
/// * `entry_point` - Description of the boot entry to set up.
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, entry_point: EntryPoint) -> Result<()> {
pub fn setup_regs(vcpu: &dyn hypervisor::Vcpu, entry_point: EntryPoint) -> Result<()> {
let mut regs = vcpu.create_standard_regs();
match entry_point.setup_header {
None => {
@@ -119,9 +118,13 @@ pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, entry_point: EntryPoint) ->
///
/// * `mem` - The memory that will be passed to the guest.
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
pub fn setup_sregs(
mem: &GuestMemoryMmap,
vcpu: &dyn hypervisor::Vcpu,
enable_x2_apic_mode: bool,
) -> Result<()> {
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
configure_segments_and_sregs(mem, &mut sregs)?;
configure_segments_and_sregs(mem, &mut sregs, enable_x2_apic_mode)?;
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
}
@@ -148,6 +151,7 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
pub fn configure_segments_and_sregs(
mem: &GuestMemoryMmap,
sregs: &mut SpecialRegisters,
enable_x2_apic_mode: bool,
) -> Result<()> {
let gdt_table: [u64; BOOT_GDT_MAX] = {
// Configure GDT entries as specified by PVH boot protocol
@@ -183,6 +187,11 @@ pub fn configure_segments_and_sregs(
sregs.cr0 = CR0_PE;
sregs.cr4 = 0;
if enable_x2_apic_mode {
const X2APIC_ENABLE_BIT: u64 = 1 << 10;
sregs.apic_base |= X2APIC_ENABLE_BIT;
}
Ok(())
}
@@ -204,7 +213,7 @@ mod tests {
fn segments_and_sregs() {
let mut sregs: SpecialRegisters = Default::default();
let gm = create_guest_mem();
configure_segments_and_sregs(&gm, &mut sregs).unwrap();
configure_segments_and_sregs(&gm, &mut sregs, false).unwrap();
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
assert_eq!(
0xcf9b000000ffff,

View File

@@ -12,8 +12,8 @@ use thiserror::Error;
use uuid::Uuid;
use vm_memory::{Address, ByteValued, Bytes, GuestAddress};
use crate::layout::SMBIOS_START;
use crate::GuestMemoryMmap;
use crate::layout::SMBIOS_START;
#[derive(Debug, Error)]
pub enum Error {
@@ -33,8 +33,8 @@ pub enum Error {
#[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),
#[error("Failure to parse uuid")]
ParseUuid(#[source] uuid::Error),
}
pub type Result<T> = result::Result<T, Error>;

View File

@@ -13,11 +13,11 @@ use crate::GuestMemoryMmap;
#[derive(Error, Debug)]
pub enum TdvfError {
#[error("Failed read TDVF descriptor: {0}")]
#[error("Failed read TDVF descriptor")]
ReadDescriptor(#[source] std::io::Error),
#[error("Failed read TDVF descriptor offset: {0}")]
#[error("Failed read TDVF descriptor offset")]
ReadDescriptorOffset(#[source] std::io::Error),
#[error("Failed read GUID table: {0}")]
#[error("Failed read GUID table")]
ReadGuidTable(#[source] std::io::Error),
#[error("Invalid descriptor signature")]
InvalidDescriptorSignature,
@@ -25,9 +25,9 @@ pub enum TdvfError {
InvalidDescriptorSize,
#[error("Invalid descriptor version")]
InvalidDescriptorVersion,
#[error("Failed to write HOB details to guest memory: {0}")]
#[error("Failed to write HOB details to guest memory")]
GuestMemoryWriteHob(#[source] GuestMemoryError),
#[error("Failed to create Uuid: {0}")]
#[error("Failed to create Uuid")]
UuidCreation(#[source] uuid::Error),
}
@@ -108,7 +108,7 @@ fn tdvf_descriptor_offset(file: &mut File) -> Result<(SeekFrom, bool), TdvfError
u16::from_le_bytes(table[offset - 18..offset - 16].try_into().unwrap()) as usize;
debug!(
"Entry GUID = {}, size = {}",
entry_uuid.hyphenated().to_string(),
entry_uuid.hyphenated(),
entry_size
);
@@ -299,7 +299,7 @@ pub struct TdHob {
}
fn align_hob(v: u64) -> u64 {
(v + 7) / 8 * 8
v.div_ceil(8) * 8
}
impl TdHob {

View File

@@ -1,6 +1,6 @@
[package]
authors = ["The Chromium OS Authors", "The Cloud Hypervisor Authors"]
edition = "2021"
edition.workspace = true
name = "block"
version = "0.1.0"
@@ -9,17 +9,17 @@ default = []
io_uring = ["dep:io-uring"]
[dependencies]
byteorder = "1.5.0"
crc-any = "2.4.4"
io-uring = { version = "0.6.4", optional = true }
libc = "0.2.167"
log = "0.4.22"
remain = "0.2.14"
serde = { version = "1.0.208", features = ["derive"] }
smallvec = "1.13.2"
thiserror = "2.0.6"
uuid = { version = "1.12.1", features = ["v4"] }
virtio-bindings = { workspace = true, features = ["virtio-v5_0_0"] }
byteorder = { workspace = true }
crc-any = "2.5.0"
io-uring = { version = "0.7.10", optional = true }
libc = { workspace = true }
log = { workspace = true }
remain = "0.2.15"
serde = { workspace = true, features = ["derive"] }
smallvec = "1.15.1"
thiserror = { workspace = true }
uuid = { workspace = true, features = ["v4"] }
virtio-bindings = { workspace = true }
virtio-queue = { workspace = true }
vm-memory = { workspace = true, features = [
"backend-atomic",

View File

@@ -2,42 +2,86 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::marker::PhantomData;
use std::os::fd::{AsRawFd, OwnedFd, RawFd};
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd;
use crate::DiskTopology;
use crate::{BatchRequest, DiskTopology};
#[derive(Error, Debug)]
pub enum DiskFileError {
/// Failed getting disk file size.
#[error("Failed getting disk file size: {0}")]
#[error("Failed getting disk file size")]
Size(#[source] std::io::Error),
/// Failed creating a new AsyncIo.
#[error("Failed creating a new AsyncIo: {0}")]
#[error("Failed creating a new AsyncIo")]
NewAsyncIo(#[source] std::io::Error),
}
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
/// A wrapper for [`RawFd`] capturing the lifetime of a corresponding [`DiskFile`].
///
/// This fulfills the same role as [`BorrowedFd`] but is tailored to the limitations
/// by some implementations of [`DiskFile`], which wrap the effective [`File`]
/// in an `Arc<Mutex<T>>`, making the use of [`BorrowedFd`] impossible.
///
/// [`BorrowedFd`]: std::os::fd::BorrowedFd
#[derive(Copy, Clone, Debug)]
pub struct BorrowedDiskFd<'fd> {
raw_fd: RawFd,
_lifetime: PhantomData<&'fd OwnedFd>,
}
impl BorrowedDiskFd<'_> {
pub(super) fn new(raw_fd: RawFd) -> Self {
Self {
raw_fd,
_lifetime: PhantomData,
}
}
}
impl AsRawFd for BorrowedDiskFd<'_> {
fn as_raw_fd(&self) -> RawFd {
self.raw_fd
}
}
/// Abstraction over the effective [`File`] backing up a block device,
/// with support for synchronous and asynchronous I/O.
///
/// This allows abstracting over raw image formats as well as structured
/// image formats.
pub trait DiskFile: Send {
fn size(&mut self) -> DiskFileResult<u64>;
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>;
fn topology(&mut self) -> DiskTopology {
DiskTopology::default()
}
/// Returns the file descriptor of the underlying disk image file.
///
/// The file descriptor is supposed to be used for `fcntl()` calls but no
/// other operation.
fn fd(&mut self) -> BorrowedDiskFd<'_>;
}
#[derive(Error, Debug)]
pub enum AsyncIoError {
/// Failed vectored reading from file.
#[error("Failed vectored reading from file: {0}")]
#[error("Failed vectored reading from file")]
ReadVectored(#[source] std::io::Error),
/// Failed vectored writing to file.
#[error("Failed vectored writing to file: {0}")]
#[error("Failed vectored writing to file")]
WriteVectored(#[source] std::io::Error),
/// Failed synchronizing file.
#[error("Failed synchronizing file: {0}")]
#[error("Failed synchronizing file")]
Fsync(#[source] std::io::Error),
/// Failed submitting batch requests.
#[error("Failed submitting batch requests")]
SubmitBatchRequests(#[source] std::io::Error),
}
pub type AsyncIoResult<T> = std::result::Result<T, AsyncIoError>;
@@ -58,4 +102,10 @@ pub trait AsyncIo: Send {
) -> AsyncIoResult<()>;
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()>;
fn next_completed_request(&mut self) -> Option<(u64, i32)>;
fn batch_requests_enabled(&self) -> bool {
false
}
fn submit_batch_requests(&mut self, _batch_request: &[BatchRequest]) -> AsyncIoResult<()> {
Ok(())
}
}

173
block/src/fcntl.rs Normal file
View File

@@ -0,0 +1,173 @@
// Copyright © 2025 Cyberus Technology GmbH
//
// SPDX-License-Identifier: Apache-2.0
//
//! Helpers for advisory file locking.
//!
//! Under the hood, the implementation uses OFD locks for the entire file,
//! as described in [[0]]. The advantage over `F_SETLKW` (currently used by
//! Rust std: `File::try_lock()`) is that only the very last `close()` on a
//! file descriptor releases the lock. This prevents mistakes and unexpected
//! behavior.
//!
//! [0]: <https://apenwarr.ca/log/20101213>.
use std::fmt::Debug;
use std::io;
use std::os::fd::{AsRawFd, RawFd};
use thiserror::Error;
/// Errors that can happen when working with file locks.
#[derive(Error, Debug)]
pub enum LockError {
/// The file is already locked.
///
/// A call to [`get_lock_state`] can help to identify the reason.
#[error("The file is already locked")]
AlreadyLocked,
/// IO error.
#[error("The lock state could not be checked or set")]
Io(#[source] io::Error),
}
/// Commands for use with [`fcntl`].
#[allow(non_camel_case_types)]
enum FcntlArg<'a> {
/// Set an OFD lock from the given lock description.
F_OFD_SETLK(&'a libc::flock),
/// Get the first OFD lock for the given lock description.
F_OFD_GETLK(&'a mut libc::flock),
}
/// Wrapper for [`libc::fcntl`] that properly sets the function arguments.
fn fcntl(fd: RawFd, arg: FcntlArg) -> libc::c_int {
// SAFETY: We use a valid FD.
unsafe {
match arg {
FcntlArg::F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
FcntlArg::F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
}
}
}
/// Describes the type of lock you want to set.
#[derive(Clone, Copy, Debug)]
pub enum LockType {
/// Clear a lock.
Unlock,
/// Set a write lock (exclusive).
Write,
/// Set a read lock (shared).
Read,
}
impl LockType {
pub const fn to_libc_val(self) -> libc::c_int {
match self {
Self::Unlock => libc::F_UNLCK as libc::c_int,
Self::Write => libc::F_WRLCK as libc::c_int,
Self::Read => libc::F_RDLCK as libc::c_int,
}
}
}
/// Describes the current state of a lock.
#[derive(Debug)]
pub enum LockState {
/// No lock set.
Unlocked,
/// Locked for reading (non-exclusive).
SharedRead,
/// Locked for writing (exclusive mode).
ExclusiveWrite,
}
impl LockState {
fn new(value: libc::c_int) -> Self {
const F_UNLCK: libc::c_int = libc::F_UNLCK as libc::c_int;
const F_WRLCK: libc::c_int = libc::F_WRLCK as libc::c_int;
const F_RDLCK: libc::c_int = libc::F_RDLCK as libc::c_int;
match value {
F_UNLCK => Self::Unlocked,
F_WRLCK => Self::ExclusiveWrite,
F_RDLCK => Self::SharedRead,
// This is so unlikely that we want to avoid the complexity of
// coping with this error case. Can only fail if either Linux
// is broken or memory is messed up.
other => panic!("Unexpected lock state: {other}"),
}
}
}
/// Returns a [`struct@libc::flock`] structure for the whole file.
const fn get_flock(lock_type: LockType) -> libc::flock {
libc::flock {
l_type: lock_type.to_libc_val() as libc::c_short,
l_whence: libc::SEEK_SET as libc::c_short,
l_start: 0,
l_len: 0, /* EOF */
l_pid: 0, /* filled by callee */
}
}
/// Tries to acquire a lock using [`fcntl`] with respect to the given
/// parameters.
///
/// Please note that `fcntl()` OFD locks are **advisory locks**, which do not
/// prevent to `open()` a file if a lock is already placed.
///
/// # Parameters
/// - `file`: The file to acquire a lock for [`LockType`]. The file's state will
/// be logically mutated, but not technically.
/// - `lock_type`: The [`LockType`]
pub fn try_acquire_lock<Fd: AsRawFd>(file: Fd, lock_type: LockType) -> Result<(), LockError> {
let flock = get_flock(lock_type);
let res = fcntl(file.as_raw_fd(), FcntlArg::F_OFD_SETLK(&flock));
match res {
0 => Ok(()),
-1 => {
let io_error = io::Error::last_os_error();
let errno = io_error.raw_os_error().unwrap();
match errno {
// See man page for error code:
// <https://man7.org/linux/man-pages/man2/fcntl.2.html>
libc::EAGAIN | libc::EACCES => Err(LockError::AlreadyLocked),
_ => Err(LockError::Io(io_error)),
}
}
val => panic!("Unexpected return value from fcntl(): {val}"),
}
}
/// Clears a lock.
///
/// # Parameters
/// - `file`: The file to clear all locks for [`LockType`].
pub fn clear_lock<Fd: AsRawFd>(file: Fd) -> Result<(), LockError> {
try_acquire_lock(file, LockType::Unlock)
}
/// Returns the current lock state using [`fcntl`] with respect to the given
/// parameters.
///
/// # Parameters
/// - `file`: The file for which to get the lock state.
pub fn get_lock_state<Fd: AsRawFd>(file: Fd) -> Result<LockState, LockError> {
let mut flock = get_flock(LockType::Write);
let res = fcntl(file.as_raw_fd(), FcntlArg::F_OFD_GETLK(&mut flock));
match res {
0 => {
let state = flock.l_type as libc::c_int;
let state = LockState::new(state);
Ok(state)
}
-1 => {
let io_error = io::Error::last_os_error();
Err(LockError::Io(io_error))
}
val => panic!("Unexpected return value from fcntl(): {val}"),
}
}

View File

@@ -6,8 +6,8 @@ use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use crate::vhd::VhdFooter;
use crate::BlockBackend;
use crate::vhd::VhdFooter;
#[derive(Debug)]
pub struct FixedVhd {

View File

@@ -8,11 +8,11 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::fixed_vhd::FixedVhd;
use crate::raw_async::RawFileAsync;
use crate::BlockBackend;
use crate::{BatchRequest, BlockBackend};
pub struct FixedVhdDiskAsync(FixedVhd);
@@ -33,6 +33,10 @@ impl DiskFile for FixedVhdDiskAsync {
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.0.as_raw_fd())
}
}
pub struct FixedVhdAsync {
@@ -102,4 +106,12 @@ impl AsyncIo for FixedVhdAsync {
fn next_completed_request(&mut self) -> Option<(u64, i32)> {
self.raw_file_async.next_completed_request()
}
fn batch_requests_enabled(&self) -> bool {
true
}
fn submit_batch_requests(&mut self, batch_request: &[BatchRequest]) -> AsyncIoResult<()> {
self.raw_file_async.submit_batch_requests(batch_request)
}
}

View File

@@ -7,12 +7,12 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::BlockBackend;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::fixed_vhd::FixedVhd;
use crate::raw_sync::RawFileSync;
use crate::BlockBackend;
pub struct FixedVhdDiskSync(FixedVhd);
@@ -33,6 +33,10 @@ impl DiskFile for FixedVhdDiskSync {
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.0.as_raw_fd())
}
}
pub struct FixedVhdSync {

View File

@@ -12,6 +12,7 @@
extern crate log;
pub mod async_io;
pub mod fcntl;
pub mod fixed_vhd;
#[cfg(feature = "io_uring")]
/// Enabled with the `"io_uring"` feature
@@ -30,7 +31,7 @@ pub mod vhd;
pub mod vhdx;
pub mod vhdx_sync;
use std::alloc::{alloc_zeroed, dealloc, Layout};
use std::alloc::{Layout, alloc_zeroed, dealloc};
use std::collections::VecDeque;
use std::fmt::Debug;
use std::fs::File;
@@ -38,13 +39,12 @@ use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use std::os::linux::fs::MetadataExt;
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::sync::{Arc, MutexGuard};
use std::time::Instant;
use std::{cmp, result};
#[cfg(feature = "io_uring")]
use io_uring::{opcode, IoUring, Probe};
use libc::{ioctl, S_IFBLK, S_IFMT};
use io_uring::{IoUring, Probe, opcode};
use libc::{S_IFBLK, S_IFMT, ioctl};
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use thiserror::Error;
@@ -56,7 +56,7 @@ use vm_memory::{
};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::{aio, ioctl_io_nr, ioctl_ioc_nr};
use vmm_sys_util::{aio, ioctl_io_nr};
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
use crate::vhdx::VhdxError;
@@ -67,9 +67,9 @@ pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
#[derive(Error, Debug)]
pub enum Error {
#[error("Guest gave us bad memory addresses")]
GuestMemory(GuestMemoryError),
GuestMemory(#[source] GuestMemoryError),
#[error("Guest gave us offsets that would have overflowed a usize")]
CheckedOffset(GuestAddress, usize),
CheckedOffset(GuestAddress, usize /* sector offset */),
#[error("Guest gave us a write only descriptor that protocol says to read from")]
UnexpectedWriteOnlyDescriptor,
#[error("Guest gave us a read only descriptor that protocol says to write to")]
@@ -78,22 +78,22 @@ pub enum Error {
DescriptorChainTooShort,
#[error("Guest gave us a descriptor that was too short to use")]
DescriptorLengthTooSmall,
#[error("Failed to detect image type: {0}")]
DetectImageType(std::io::Error),
#[error("Failure in fixed vhd: {0}")]
FixedVhdError(std::io::Error),
#[error("Failed to detect image type")]
DetectImageType(#[source] std::io::Error),
#[error("Failure in fixed vhd")]
FixedVhdError(#[source] std::io::Error),
#[error("Getting a block's metadata fails for any reason")]
GetFileMetadata,
#[error("The requested operation would cause a seek beyond disk end")]
InvalidOffset,
#[error("Failure in qcow: {0}")]
QcowError(qcow::Error),
#[error("Failure in raw file: {0}")]
RawFileError(std::io::Error),
#[error("Failure in qcow")]
QcowError(#[source] qcow::Error),
#[error("Failure in raw file")]
RawFileError(#[source] std::io::Error),
#[error("The requested operation does not support multiple descriptors")]
TooManyDescriptors,
#[error("Failure in vhdx: {0}")]
VhdxError(VhdxError),
#[error("Failure in vhdx")]
VhdxError(#[source] VhdxError),
}
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
@@ -130,34 +130,36 @@ pub fn build_serial(disk_path: &Path) -> Vec<u8> {
#[derive(Error, Debug)]
pub enum ExecuteError {
#[error("Bad request: {0}")]
BadRequest(Error),
#[error("Failed to flush: {0}")]
Flush(io::Error),
#[error("Failed to read: {0}")]
Read(GuestMemoryError),
#[error("Failed to read_exact: {0}")]
ReadExact(io::Error),
#[error("Failed to seek: {0}")]
Seek(io::Error),
#[error("Failed to write: {0}")]
Write(GuestMemoryError),
#[error("Failed to write_all: {0}")]
WriteAll(io::Error),
#[error("Bad request")]
BadRequest(#[source] Error),
#[error("Failed to flush")]
Flush(#[source] io::Error),
#[error("Failed to read")]
Read(#[source] GuestMemoryError),
#[error("Failed to read_exact")]
ReadExact(#[source] io::Error),
#[error("Can't execute an operation other than `read` on a read-only device")]
ReadOnly,
#[error("Failed to seek")]
Seek(#[source] io::Error),
#[error("Failed to write")]
Write(#[source] GuestMemoryError),
#[error("Failed to write_all")]
WriteAll(#[source] io::Error),
#[error("Unsupported request: {0}")]
Unsupported(u32),
#[error("Failed to submit io uring: {0}")]
SubmitIoUring(io::Error),
#[error("Failed to get guest address: {0}")]
GetHostAddress(GuestMemoryError),
#[error("Failed to async read: {0}")]
AsyncRead(AsyncIoError),
#[error("Failed to async write: {0}")]
AsyncWrite(AsyncIoError),
#[error("failed to async flush: {0}")]
AsyncFlush(AsyncIoError),
#[error("Failed allocating a temporary buffer: {0}")]
TemporaryBufferAllocation(io::Error),
#[error("Failed to submit io uring")]
SubmitIoUring(#[source] io::Error),
#[error("Failed to get guest address")]
GetHostAddress(#[source] GuestMemoryError),
#[error("Failed to async read")]
AsyncRead(#[source] AsyncIoError),
#[error("Failed to async write")]
AsyncWrite(#[source] AsyncIoError),
#[error("failed to async flush")]
AsyncFlush(#[source] AsyncIoError),
#[error("Failed allocating a temporary buffer")]
TemporaryBufferAllocation(#[source] io::Error),
}
impl ExecuteError {
@@ -167,6 +169,7 @@ impl ExecuteError {
ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::ReadExact(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::ReadOnly => VIRTIO_BLK_S_IOERR,
ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::WriteAll(_) => VIRTIO_BLK_S_IOERR,
@@ -228,6 +231,20 @@ pub struct AlignedOperation {
layout: Layout,
}
pub struct BatchRequest {
pub offset: libc::off_t,
pub iovecs: SmallVec<[libc::iovec; DEFAULT_DESCRIPTOR_VEC_SIZE]>,
pub user_data: u64,
pub request_type: RequestType,
}
pub struct ExecuteAsync {
// `true` if the execution will complete asynchronously
pub async_complete: bool,
// request need to be batched for submission if any
pub batch_request: Option<BatchRequest>,
}
#[derive(Debug)]
pub struct Request {
pub request_type: RequestType,
@@ -242,7 +259,7 @@ pub struct Request {
impl Request {
pub fn parse<B: Bitmap + 'static>(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
access_platform: Option<&Arc<dyn AccessPlatform>>,
access_platform: Option<&dyn AccessPlatform>,
) -> result::Result<Request, Error> {
let hdr_desc = desc_chain
.next()
@@ -275,14 +292,14 @@ impl Request {
.next()
.ok_or(Error::DescriptorChainTooShort)
.inspect_err(|_| {
error!("Only head descriptor present: request = {:?}", req);
error!("Only head descriptor present: request = {req:?}");
})?;
if !desc.has_next() {
status_desc = desc;
// Only flush requests are allowed to skip the data descriptor.
if req.request_type != RequestType::Flush {
error!("Need a data descriptor: request = {:?}", req);
error!("Need a data descriptor: request = {req:?}");
return Err(Error::DescriptorChainTooShort);
}
} else {
@@ -307,7 +324,7 @@ impl Request {
.next()
.ok_or(Error::DescriptorChainTooShort)
.inspect_err(|_| {
error!("DescriptorChain corrupted: request = {:?}", req);
error!("DescriptorChain corrupted: request = {req:?}");
})?;
}
status_desc = desc;
@@ -393,21 +410,27 @@ impl Request {
disk_image: &mut dyn AsyncIo,
serial: &[u8],
user_data: u64,
) -> result::Result<bool, ExecuteError> {
) -> result::Result<ExecuteAsync, ExecuteError> {
let sector = self.sector;
let request_type = self.request_type;
let offset = (sector << SECTOR_SHIFT) as libc::off_t;
let mut iovecs: SmallVec<[libc::iovec; DEFAULT_DESCRIPTOR_VEC_SIZE]> =
SmallVec::with_capacity(self.data_descriptors.len());
for (data_addr, data_len) in &self.data_descriptors {
if *data_len == 0 {
for &(data_addr, data_len) in &self.data_descriptors {
let _: u32 = data_len; // compiler-checked documentation
const _: () = assert!(
core::mem::size_of::<u32>() <= core::mem::size_of::<usize>(),
"unsupported platform"
);
if data_len == 0 {
continue;
}
let mut top: u64 = u64::from(*data_len) / SECTOR_SIZE;
if u64::from(*data_len) % SECTOR_SIZE != 0 {
let mut top: u64 = u64::from(data_len) / SECTOR_SIZE;
if u64::from(data_len) % SECTOR_SIZE != 0 {
top += 1;
}
let data_len = data_len as usize;
top = top
.checked_add(sector)
.ok_or(ExecuteError::BadRequest(Error::InvalidOffset))?;
@@ -416,7 +439,7 @@ impl Request {
}
let origin_ptr = mem
.get_slice(*data_addr, *data_len as usize)
.get_slice(data_addr, data_len)
.map_err(ExecuteError::GetHostAddress)?
.ptr_guard();
@@ -424,9 +447,8 @@ impl Request {
// In case it's not properly aligned, an intermediate buffer is
// created with the correct alignment, and a copy from/to the
// origin buffer is performed, depending on the type of operation.
let iov_base = if (origin_ptr.as_ptr() as u64) % SECTOR_SIZE != 0 {
let layout =
Layout::from_size_align(*data_len as usize, SECTOR_SIZE as usize).unwrap();
let iov_base = if !(origin_ptr.as_ptr() as u64).is_multiple_of(SECTOR_SIZE) {
let layout = Layout::from_size_align(data_len, SECTOR_SIZE as usize).unwrap();
// SAFETY: layout has non-zero size
let aligned_ptr = unsafe { alloc_zeroed(layout) };
if aligned_ptr.is_null() {
@@ -440,7 +462,7 @@ impl Request {
if request_type == RequestType::Out {
// SAFETY: destination buffer has been allocated with
// the proper size.
unsafe { std::ptr::copy(origin_ptr.as_ptr(), aligned_ptr, *data_len as usize) };
unsafe { std::ptr::copy(origin_ptr.as_ptr(), aligned_ptr, data_len) };
}
// Store both origin and aligned pointers for complete_async()
@@ -448,7 +470,7 @@ impl Request {
self.aligned_operations.push(AlignedOperation {
origin_ptr: origin_ptr.as_ptr() as u64,
aligned_ptr: aligned_ptr as u64,
size: *data_len as usize,
size: data_len,
layout,
});
@@ -459,11 +481,15 @@ impl Request {
let iovec = libc::iovec {
iov_base,
iov_len: *data_len as libc::size_t,
iov_len: data_len as libc::size_t,
};
iovecs.push(iovec);
}
let mut ret = ExecuteAsync {
async_complete: true,
batch_request: None,
};
// Queue operations expected to be submitted.
match request_type {
RequestType::In => {
@@ -473,14 +499,32 @@ impl Request {
.bitmap()
.mark_dirty(0, *data_len as usize);
}
disk_image
.read_vectored(offset, &iovecs, user_data)
.map_err(ExecuteError::AsyncRead)?;
if disk_image.batch_requests_enabled() {
ret.batch_request = Some(BatchRequest {
offset,
iovecs,
user_data,
request_type,
});
} else {
disk_image
.read_vectored(offset, &iovecs, user_data)
.map_err(ExecuteError::AsyncRead)?;
}
}
RequestType::Out => {
disk_image
.write_vectored(offset, &iovecs, user_data)
.map_err(ExecuteError::AsyncWrite)?;
if disk_image.batch_requests_enabled() {
ret.batch_request = Some(BatchRequest {
offset,
iovecs,
user_data,
request_type,
});
} else {
disk_image
.write_vectored(offset, &iovecs, user_data)
.map_err(ExecuteError::AsyncWrite)?;
}
}
RequestType::Flush => {
disk_image
@@ -498,12 +542,13 @@ impl Request {
}
mem.write_slice(serial, data_addr)
.map_err(ExecuteError::Write)?;
return Ok(false);
ret.async_complete = false;
return Ok(ret);
}
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
}
Ok(true)
Ok(ret)
}
pub fn complete_async(&mut self) -> result::Result<(), Error> {
@@ -640,10 +685,7 @@ pub fn block_io_uring_is_supported() -> bool {
}
}
pub trait AsyncAdaptor<F>
where
F: Read + Write + Seek,
{
pub trait AsyncAdaptor {
fn read_vectored_sync(
&mut self,
offset: libc::off_t,
@@ -651,7 +693,10 @@ where
user_data: u64,
eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> {
) -> AsyncIoResult<()>
where
Self: Read + Seek,
{
// Convert libc::iovec into IoSliceMut
let mut slices: SmallVec<[IoSliceMut; DEFAULT_DESCRIPTOR_VEC_SIZE]> =
SmallVec::with_capacity(iovecs.len());
@@ -663,15 +708,13 @@ where
}
let result = {
let mut file = self.file();
// Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64))
self.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::ReadVectored)?;
let mut r = 0;
for b in slices.iter_mut() {
r += file.read(b).map_err(AsyncIoError::ReadVectored)?;
r += self.read(b).map_err(AsyncIoError::ReadVectored)?;
}
r
};
@@ -689,7 +732,10 @@ where
user_data: u64,
eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> {
) -> AsyncIoResult<()>
where
Self: Write + Seek,
{
// Convert libc::iovec into IoSlice
let mut slices: SmallVec<[IoSlice; DEFAULT_DESCRIPTOR_VEC_SIZE]> =
SmallVec::with_capacity(iovecs.len());
@@ -701,15 +747,13 @@ where
}
let result = {
let mut file = self.file();
// Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64))
self.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::WriteVectored)?;
let mut r = 0;
for b in slices.iter() {
r += file.write(b).map_err(AsyncIoError::WriteVectored)?;
r += self.write(b).map_err(AsyncIoError::WriteVectored)?;
}
r
};
@@ -725,12 +769,13 @@ where
user_data: Option<u64>,
eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> {
) -> AsyncIoResult<()>
where
Self: Write,
{
let result: i32 = {
let mut file = self.file();
// Flush
file.flush().map_err(AsyncIoError::Fsync)?;
self.flush().map_err(AsyncIoError::Fsync)?;
0
};
@@ -742,8 +787,6 @@ where
Ok(())
}
fn file(&mut self) -> MutexGuard<F>;
}
pub enum ImageType {

View File

@@ -13,6 +13,7 @@ use std::cmp::{max, min};
use std::fs::OpenOptions;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::mem::size_of;
use std::os::fd::{AsRawFd, RawFd};
use std::str;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
@@ -23,11 +24,11 @@ use vmm_sys_util::file_traits::{FileSetLen, FileSync};
use vmm_sys_util::seek_hole::SeekHole;
use vmm_sys_util::write_zeroes::{PunchHole, WriteZeroesAt};
use crate::BlockBackend;
use crate::qcow::qcow_raw_file::QcowRawFile;
pub use crate::qcow::raw_file::RawFile;
use crate::qcow::refcount::RefCount;
use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
use crate::BlockBackend;
/// Nesting depth limit for disk formats that can open other disk files.
const MAX_NESTING_DEPTH: u32 = 10;
@@ -35,24 +36,24 @@ const MAX_NESTING_DEPTH: u32 = 10;
#[sorted]
#[derive(Debug, Error)]
pub enum Error {
#[error("Backing file io error: {0}")]
BackingFileIo(io::Error),
#[error("Backing file open error: {0}")]
BackingFileOpen(Box<Error>),
#[error("Backing file io error")]
BackingFileIo(#[source] io::Error),
#[error("Backing file open error")]
BackingFileOpen(#[source] 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("Failed to evict cache")]
EvictingCache(#[source] io::Error),
#[error("File larger than max of {MAX_QCOW_FILE_SIZE}: {0}")]
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("Failed to get file size")]
GettingFileSize(#[source] io::Error),
#[error("Failed to get refcount")]
GettingRefcount(#[source] refcount::Error),
#[error("Failed to parse filename")]
InvalidBackingFileName(#[source] str::Utf8Error),
#[error("Invalid cluster index")]
InvalidClusterIndex,
#[error("Invalid cluster size")]
@@ -80,29 +81,29 @@ pub enum Error {
#[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),
OpeningFile(#[source] io::Error),
#[error("Failed to read data")]
ReadingData(#[source] io::Error),
#[error("Failed to read header")]
ReadingHeader(#[source] io::Error),
#[error("Failed to read pointers")]
ReadingPointers(#[source] io::Error),
#[error("Failed to read ref count block")]
ReadingRefCountBlock(#[source] refcount::Error),
#[error("Failed to read ref counts")]
ReadingRefCounts(#[source] io::Error),
#[error("Failed to rebuild ref counts")]
RebuildingRefCounts(#[source] 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("Failed to seek file")]
SeekingFile(#[source] io::Error),
#[error("Failed to set file size")]
SettingFileSize(#[source] io::Error),
#[error("Failed to set refcount refcount")]
SettingRefcountRefcount(#[source] io::Error),
#[error("Size too small for number of clusters")]
SizeTooSmallForNumberOfClusters,
#[error("L1 entry table too large: {0}")]
@@ -113,10 +114,10 @@ pub enum Error {
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),
#[error("Failed to write data")]
WritingData(#[source] io::Error),
#[error("Failed to write header")]
WritingHeader(#[source] io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
@@ -286,11 +287,12 @@ impl QcowHeader {
let cluster_bits: u32 = DEFAULT_CLUSTER_BITS;
let cluster_size: u32 = 0x01 << cluster_bits;
let max_length: usize = (cluster_size - header_size) as usize;
if let Some(path) = backing_file {
if path.len() > max_length {
return Err(Error::BackingFileTooLong(path.len() - max_length));
}
if let Some(path) = backing_file
&& path.len() > max_length
{
return Err(Error::BackingFileTooLong(path.len() - max_length));
}
// L2 blocks are always one cluster long. They contain cluster_size/sizeof(u64) addresses.
let entries_per_cluster: u32 = cluster_size / size_of::<u64>() as u32;
let num_clusters: u32 = div_round_up_u64(size, u64::from(cluster_size)) as u32;
@@ -378,7 +380,7 @@ impl QcowHeader {
}
if let Some(backing_file_path) = self.backing_file_path.as_ref() {
write!(file, "{}", backing_file_path).map_err(Error::WritingHeader)?;
write!(file, "{backing_file_path}").map_err(Error::WritingHeader)?;
}
// Set the file length by seeking and writing a zero to the last byte. This avoids needing
@@ -424,7 +426,7 @@ fn max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct QcowFile {
raw_file: QcowRawFile,
header: QcowHeader,
@@ -502,7 +504,7 @@ impl QcowFile {
if refcount_bits != 16 {
return Err(Error::UnsupportedRefcountOrder);
}
let refcount_bytes = (refcount_bits + 7) / 8;
let refcount_bytes = refcount_bits.div_ceil(8);
// Need at least one refcount cluster
if header.refcount_table_clusters == 0 {
@@ -588,14 +590,12 @@ impl QcowFile {
// Check for compressed blocks
for l2_addr_disk in l1_table.get_values() {
if *l2_addr_disk != 0 {
if let Err(e) = Self::read_l2_cluster(&mut raw_file, *l2_addr_disk) {
if let Some(os_error) = e.raw_os_error() {
if os_error == ENOTSUP {
return Err(Error::CompressedBlocksNotSupported);
}
}
}
if *l2_addr_disk != 0
&& let Err(e) = Self::read_l2_cluster(&mut raw_file, *l2_addr_disk)
&& let Some(os_error) = e.raw_os_error()
&& os_error == ENOTSUP
{
return Err(Error::CompressedBlocksNotSupported);
}
}
@@ -1070,21 +1070,7 @@ impl QcowFile {
let l2_index = self.l2_table_index(address) as usize;
if !self.l2_cache.contains_key(l1_index) {
// Not in the cache.
let table =
VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
let l1_table = &self.l1_table;
let raw_file = &mut self.raw_file;
self.l2_cache.insert(l1_index, table, |index, evicted| {
raw_file.write_pointer_table(
l1_table[index],
evicted.get_values(),
CLUSTER_USED_FLAG,
)
})?;
};
self.cache_l2_cluster(l1_index, l2_addr_disk, false)?;
let cluster_addr = self.l2_cache.get(l1_index).unwrap()[l2_index];
if cluster_addr == 0 {
@@ -1109,28 +1095,9 @@ impl QcowFile {
let mut set_refcounts = Vec::new();
if !self.l2_cache.contains_key(l1_index) {
// Not in the cache.
let l2_table = if l2_addr_disk == 0 {
// Allocate a new cluster to store the L2 table and update the L1 table to point
// to the new table.
let new_addr: u64 = self.get_new_cluster(None)?;
// The cluster refcount starts at one meaning it is used but doesn't need COW.
set_refcounts.push((new_addr, 1));
self.l1_table[l1_index] = new_addr;
VecCache::new(self.l2_entries as usize)
} else {
VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?)
};
let l1_table = &self.l1_table;
let raw_file = &mut self.raw_file;
self.l2_cache.insert(l1_index, l2_table, |index, evicted| {
raw_file.write_pointer_table(
l1_table[index],
evicted.get_values(),
CLUSTER_USED_FLAG,
)
})?;
if let Some(new_addr) = self.cache_l2_cluster(l1_index, l2_addr_disk, true)? {
// The cluster refcount starts at one meaning it is used but doesn't need COW.
set_refcounts.push((new_addr, 1));
}
let cluster_addr = match self.l2_cache.get(l1_index).unwrap()[l2_index] {
@@ -1247,20 +1214,7 @@ impl QcowFile {
return Ok(false);
}
if !self.l2_cache.contains_key(l1_index) {
// Not in the cache.
let table =
VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
let l1_table = &self.l1_table;
let raw_file = &mut self.raw_file;
self.l2_cache.insert(l1_index, table, |index, evicted| {
raw_file.write_pointer_table(
l1_table[index],
evicted.get_values(),
CLUSTER_USED_FLAG,
)
})?;
}
self.cache_l2_cluster(l1_index, l2_addr_disk, false)?;
let cluster_addr = self.l2_cache.get(l1_index).unwrap()[l2_index];
// If cluster_addr != 0, the cluster is allocated.
@@ -1319,20 +1273,7 @@ impl QcowFile {
return Ok(());
}
if !self.l2_cache.contains_key(l1_index) {
// Not in the cache.
let table =
VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
let l1_table = &self.l1_table;
let raw_file = &mut self.raw_file;
self.l2_cache.insert(l1_index, table, |index, evicted| {
raw_file.write_pointer_table(
l1_table[index],
evicted.get_values(),
CLUSTER_USED_FLAG,
)
})?;
}
self.cache_l2_cluster(l1_index, l2_addr_disk, false)?;
let cluster_addr = self.l2_cache.get(l1_index).unwrap()[l2_index];
if cluster_addr == 0 {
@@ -1417,6 +1358,41 @@ impl QcowFile {
.collect())
}
// Put an L2 cluster to the cache with evicting less-used cluster
// The new cluster may be allocated if necessary
// (may_alloc argument is true and l2_addr_disk == 0)
fn cache_l2_cluster(
&mut self,
l1_index: usize,
l2_addr_disk: u64,
may_alloc: bool,
) -> std::io::Result<Option<u64>> {
let mut new_cluster: Option<u64> = None;
if !self.l2_cache.contains_key(l1_index) {
// Not in the cache.
let l2_table = if may_alloc && l2_addr_disk == 0 {
// Allocate a new cluster to store the L2 table and update the L1 table to point
// to the new table.
let new_addr: u64 = self.get_new_cluster(None)?;
new_cluster = Some(new_addr);
self.l1_table[l1_index] = new_addr;
VecCache::new(self.l2_entries as usize)
} else {
VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?)
};
let l1_table = &self.l1_table;
let raw_file = &mut self.raw_file;
self.l2_cache.insert(l1_index, l2_table, |index, evicted| {
raw_file.write_pointer_table(
l1_table[index],
evicted.get_values(),
CLUSTER_USED_FLAG,
)
})?;
}
Ok(new_cluster)
}
// Set the refcount for a cluster with the given address.
// Returns a list of any refblocks that can be reused, this happens when a refblock is moved,
// the old location can be reused.
@@ -1516,6 +1492,12 @@ impl QcowFile {
}
}
impl AsRawFd for QcowFile {
fn as_raw_fd(&self) -> RawFd {
self.raw_file.as_raw_fd()
}
}
impl Drop for QcowFile {
fn drop(&mut self) {
let _ = self.sync_caches();
@@ -1577,11 +1559,11 @@ impl Seek for QcowFile {
}
};
if let Some(o) = new_offset {
if o <= self.virtual_size() {
self.current_offset = o;
return Ok(o);
}
if let Some(o) = new_offset
&& o <= self.virtual_size()
{
self.current_offset = o;
return Ok(o);
}
Err(std::io::Error::from_raw_os_error(EINVAL))
}
@@ -1625,8 +1607,7 @@ impl FileSync for QcowFile {
impl FileSetLen for QcowFile {
fn set_len(&self, _len: u64) -> std::io::Result<()> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
Err(std::io::Error::other(
"set_len() not supported for QcowFile",
))
}
@@ -1699,12 +1680,12 @@ fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
// Ceiling of the division of `dividend`/`divisor`.
fn div_round_up_u64(dividend: u64, divisor: u64) -> u64 {
dividend / divisor + u64::from(dividend % divisor != 0)
dividend / divisor + u64::from(!dividend.is_multiple_of(divisor))
}
// Ceiling of the division of `dividend`/`divisor`.
fn div_round_up_u32(dividend: u32, divisor: u32) -> u32 {
dividend / divisor + u32::from(dividend % divisor != 0)
dividend / divisor + u32::from(!dividend.is_multiple_of(divisor))
}
fn convert_copy<R, W>(reader: &mut R, writer: &mut W, offset: u64, size: u64) -> Result<()>

View File

@@ -6,6 +6,7 @@
use std::io::{self, BufWriter, Seek, SeekFrom, Write};
use std::mem::size_of;
use std::os::fd::{AsRawFd, RawFd};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use vmm_sys_util::write_zeroes::WriteZeroes;
@@ -35,7 +36,7 @@ impl QcowRawFile {
}
/// Reads `count` 64 bit offsets and returns them as a vector.
/// `mask` optionally ands out some of the bits on the file.
/// `mask` optionally `&`s out some of the bits on the file.
pub fn read_pointer_table(
&mut self,
offset: u64,
@@ -54,7 +55,7 @@ impl QcowRawFile {
}
/// Reads a cluster's worth of 64 bit offsets and returns them as a vector.
/// `mask` optionally ands out some of the bits on the file.
/// `mask` optionally `&`s out some of the bits on the file.
pub fn read_pointer_cluster(&mut self, offset: u64, mask: Option<u64>) -> io::Result<Vec<u64>> {
let count = self.cluster_size / size_of::<u64>() as u64;
self.read_pointer_table(offset, count, mask)
@@ -159,3 +160,9 @@ impl Clone for QcowRawFile {
}
}
}
impl AsRawFd for QcowRawFile {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}

View File

@@ -8,7 +8,7 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::alloc::{alloc_zeroed, dealloc, Layout};
use std::alloc::{Layout, alloc_zeroed, dealloc};
use std::fs::{File, Metadata};
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::os::unix::io::{AsRawFd, RawFd};
@@ -89,9 +89,9 @@ impl RawFile {
let align64: u64 = self.alignment.try_into().unwrap();
(self.position % align64 == 0)
&& ((buf.as_ptr() as usize) % self.alignment == 0)
&& (buf.len() % self.alignment == 0)
self.position.is_multiple_of(align64)
&& (buf.as_ptr() as usize).is_multiple_of(self.alignment)
&& buf.len().is_multiple_of(self.alignment)
}
pub fn set_len(&self, size: u64) -> std::io::Result<()> {
@@ -369,3 +369,9 @@ impl Clone for RawFile {
}
}
}
impl AsRawFd for RawFile {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}

View File

@@ -15,8 +15,8 @@ use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
#[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),
#[error("Failed to write a refblock from the cache to disk")]
EvictingRefCounts(#[source] 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,
@@ -27,8 +27,8 @@ pub enum Error {
#[error("New cluster needs to be allocated for refcounts")]
NeedNewCluster,
/// `ReadingRefCounts` - Error reading the file into the refcount cache.
#[error("Failed to read the file into the refcount cache: {0}")]
ReadingRefCounts(io::Error),
#[error("Failed to read the file into the refcount cache")]
ReadingRefCounts(#[source] io::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@@ -4,8 +4,8 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use std::collections::hash_map::IterMut;
use std::collections::HashMap;
use std::collections::hash_map::IterMut;
use std::io;
use std::ops::{Index, IndexMut};
use std::slice::SliceIndex;
@@ -111,7 +111,7 @@ impl<T: Cacheable> CacheMap<T> {
self.map.get_mut(&index)
}
pub fn iter_mut(&mut self) -> IterMut<usize, T> {
pub fn iter_mut(&mut self) -> IterMut<'_, usize, T> {
self.map.iter_mut()
}
@@ -123,10 +123,10 @@ impl<T: Cacheable> CacheMap<T> {
if self.map.len() == self.capacity {
// TODO(dgreid) - smarter eviction strategy.
let to_evict = *self.map.iter().next().unwrap().0;
if let Some(evicted) = self.map.remove(&to_evict) {
if evicted.dirty() {
write_callback(to_evict, evicted)?;
}
if let Some(evicted) = self.map.remove(&to_evict)
&& evicted.dirty()
{
write_callback(to_evict, evicted)?;
}
}
self.map.insert(index, block);

View File

@@ -5,46 +5,52 @@
use std::collections::VecDeque;
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::sync::{Arc, Mutex, MutexGuard};
use std::os::fd::AsRawFd;
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
use crate::qcow::{QcowFile, RawFile, Result as QcowResult};
use crate::AsyncAdaptor;
use crate::async_io::{
AsyncIo, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::qcow::{QcowFile, RawFile, Result as QcowResult};
pub struct QcowDiskSync {
qcow_file: Arc<Mutex<QcowFile>>,
qcow_file: QcowFile,
}
impl QcowDiskSync {
pub fn new(file: File, direct_io: bool) -> QcowResult<Self> {
Ok(QcowDiskSync {
qcow_file: Arc::new(Mutex::new(QcowFile::from(RawFile::new(file, direct_io))?)),
qcow_file: QcowFile::from(RawFile::new(file, direct_io))?,
})
}
}
impl DiskFile for QcowDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
let mut file = self.qcow_file.lock().unwrap();
file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size)
self.qcow_file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(QcowSync::new(self.qcow_file.clone())) as Box<dyn AsyncIo>)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.qcow_file.as_raw_fd())
}
}
pub struct QcowSync {
qcow_file: Arc<Mutex<QcowFile>>,
qcow_file: QcowFile,
eventfd: EventFd,
completion_list: VecDeque<(u64, i32)>,
}
impl QcowSync {
pub fn new(qcow_file: Arc<Mutex<QcowFile>>) -> Self {
pub fn new(qcow_file: QcowFile) -> Self {
QcowSync {
qcow_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)
@@ -54,11 +60,7 @@ impl QcowSync {
}
}
impl AsyncAdaptor<QcowFile> for Arc<Mutex<QcowFile>> {
fn file(&mut self) -> MutexGuard<QcowFile> {
self.lock().unwrap()
}
}
impl AsyncAdaptor for QcowFile {}
impl AsyncIo for QcowSync {
fn notifier(&self) -> &EventFd {

View File

@@ -6,13 +6,13 @@ use std::fs::File;
use std::io::{Error, Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};
use io_uring::{opcode, types, IoUring};
use io_uring::{IoUring, opcode, types};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
use crate::{BatchRequest, DiskTopology, RequestType};
pub struct RawFileDisk {
file: File,
@@ -46,6 +46,10 @@ impl DiskFile for RawFileDisk {
DiskTopology::default()
}
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}
pub struct RawFileAsync {
@@ -164,4 +168,77 @@ impl AsyncIo for RawFileAsync {
.next()
.map(|entry| (entry.user_data(), entry.result()))
}
fn batch_requests_enabled(&self) -> bool {
true
}
fn submit_batch_requests(&mut self, batch_request: &[BatchRequest]) -> AsyncIoResult<()> {
if !self.batch_requests_enabled() {
return Ok(());
}
let (submitter, mut sq, _) = self.io_uring.split();
let mut submitted = false;
for req in batch_request {
match req.request_type {
RequestType::In => {
// SAFETY: we know the file descriptor is valid and we
// relied on vm-memory to provide the buffer address.
unsafe {
sq.push(
&opcode::Readv::new(
types::Fd(self.fd),
req.iovecs.as_ptr(),
req.iovecs.len() as u32,
)
.offset(req.offset as u64)
.build()
.user_data(req.user_data),
)
.map_err(|_| {
AsyncIoError::ReadVectored(Error::other("Submission queue is full"))
})?
};
submitted = true;
}
RequestType::Out => {
// SAFETY: we know the file descriptor is valid and we
// relied on vm-memory to provide the buffer address.
unsafe {
sq.push(
&opcode::Writev::new(
types::Fd(self.fd),
req.iovecs.as_ptr(),
req.iovecs.len() as u32,
)
.offset(req.offset as u64)
.build()
.user_data(req.user_data),
)
.map_err(|_| {
AsyncIoError::WriteVectored(Error::other("Submission queue is full"))
})?
};
submitted = true;
}
_ => {
unreachable!("Unexpected batch request type: {:?}", req.request_type)
}
}
}
// Only submit if we actually queued something
if submitted {
// Update the submission queue and submit new operations to the
// io_uring instance.
sq.sync();
submitter
.submit()
.map_err(AsyncIoError::SubmitBatchRequests)?;
}
Ok(())
}
}

View File

@@ -12,10 +12,10 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
pub struct RawFileDiskAio {
file: File,
@@ -49,6 +49,10 @@ impl DiskFile for RawFileDiskAio {
DiskTopology::default()
}
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}
pub struct RawFileAsyncAio {

View File

@@ -9,10 +9,10 @@ use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use crate::DiskTopology;
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
pub struct RawFileDiskSync {
file: File,
@@ -43,6 +43,10 @@ impl DiskFile for RawFileDiskSync {
DiskTopology::default()
}
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}
pub struct RawFileSync {

View File

@@ -5,7 +5,7 @@
use std::fs::File;
use std::io::{Seek, SeekFrom};
use crate::{read_aligned_block_size, DiskTopology};
use crate::{DiskTopology, read_aligned_block_size};
#[derive(Clone, Copy)]
pub struct VhdFooter {
@@ -123,7 +123,7 @@ mod tests {
use vmm_sys_util::tempfile::TempFile;
use super::{is_fixed_vhd, VhdFooter};
use super::{VhdFooter, is_fixed_vhd};
fn valid_fixed_vhd_footer() -> Vec<u8> {
vec![

View File

@@ -5,17 +5,18 @@
use std::collections::btree_map::BTreeMap;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::os::fd::{AsRawFd, RawFd};
use byteorder::{BigEndian, ByteOrder};
use remain::sorted;
use thiserror::Error;
use uuid::Uuid;
use crate::BlockBackend;
use crate::vhdx::vhdx_bat::{BatEntry, VhdxBatError};
use crate::vhdx::vhdx_header::{RegionInfo, RegionTableEntry, VhdxHeader, VhdxHeaderError};
use crate::vhdx::vhdx_io::VhdxIoError;
use crate::vhdx::vhdx_metadata::{DiskSpec, VhdxMetadataError};
use crate::BlockBackend;
mod vhdx_bat;
mod vhdx_header;
@@ -25,19 +26,19 @@ mod vhdx_metadata;
#[sorted]
#[derive(Error, Debug)]
pub enum VhdxError {
#[error("Not a VHDx file {0}")]
#[error("Not a VHDx file")]
NotVhdx(#[source] VhdxHeaderError),
#[error("Failed to parse VHDx header {0}")]
#[error("Failed to parse VHDx header")]
ParseVhdxHeader(#[source] VhdxHeaderError),
#[error("Failed to parse VHDx metadata {0}")]
#[error("Failed to parse VHDx metadata")]
ParseVhdxMetadata(#[source] VhdxMetadataError),
#[error("Failed to parse VHDx region entries {0}")]
#[error("Failed to parse VHDx region entries")]
ParseVhdxRegionEntry(#[source] VhdxHeaderError),
#[error("Failed reading metadata {0}")]
#[error("Failed reading metadata")]
ReadBatEntry(#[source] VhdxBatError),
#[error("Failed reading sector from disk {0}")]
#[error("Failed reading sector from disk")]
ReadFailed(#[source] VhdxIoError),
#[error("Failed writing to sector on disk {0}")]
#[error("Failed writing to sector on disk")]
WriteFailed(#[source] VhdxIoError),
}
@@ -111,12 +112,9 @@ impl Read for Vhdx {
sector_count,
)
.map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"Failed reading {sector_count} sectors from VHDx at index {sector_index}: {e}"
),
)
std::io::Error::other(format!(
"Failed reading {sector_count} sectors from VHDx at index {sector_index}: {e}"
))
})?;
self.current_offset = self.current_offset.checked_add(result as u64).unwrap();
@@ -138,12 +136,9 @@ impl Write for Vhdx {
if self.first_write {
self.first_write = false;
self.vhdx_header.update(&mut self.file).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!("Failed to update VHDx header: {e}"),
)
})?;
self.vhdx_header
.update(&mut self.file)
.map_err(|e| std::io::Error::other(format!("Failed to update VHDx header: {e}")))?;
}
let result = vhdx_io::write(
@@ -156,12 +151,9 @@ impl Write for Vhdx {
sector_count,
)
.map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"Failed writing {sector_count} sectors on VHDx at index {sector_index}: {e}"
),
)
std::io::Error::other(format!(
"Failed writing {sector_count} sectors on VHDx at index {sector_index}: {e}"
))
})?;
self.current_offset = self.current_offset.checked_add(result as u64).unwrap();
@@ -195,11 +187,11 @@ impl Seek for Vhdx {
}
};
if let Some(o) = new_offset {
if o <= self.virtual_disk_size() {
self.current_offset = o;
return Ok(o);
}
if let Some(o) = new_offset
&& o <= self.virtual_disk_size()
{
self.current_offset = o;
return Ok(o);
}
Err(std::io::Error::new(
@@ -231,6 +223,12 @@ impl Clone for Vhdx {
}
}
impl AsRawFd for Vhdx {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
pub(crate) fn uuid_from_guid(buf: &[u8]) -> Uuid {
// The first 3 fields of UUID are stored in Big Endian format, and
// the last 8 bytes are stored as byte array. Therefore, we read the

View File

@@ -33,9 +33,9 @@ pub enum VhdxBatError {
InvalidBatEntry,
#[error("Invalid BAT entry count")]
InvalidEntryCount,
#[error("Failed to read BAT entry {0}")]
#[error("Failed to read BAT entry")]
ReadBat(#[source] io::Error),
#[error("Failed to write BAT entry {0}")]
#[error("Failed to write BAT entry")]
WriteBat(#[source] io::Error),
}

View File

@@ -35,9 +35,7 @@ pub enum VhdxIoError {
pub type Result<T> = std::result::Result<T, VhdxIoError>;
macro_rules! align {
($n:expr, $align:expr) => {{
$n.div_ceil($align) * $align
}};
($n:expr, $align:expr) => {{ $n.div_ceil($align) * $align }};
}
#[derive(Default)]

View File

@@ -4,29 +4,31 @@
use std::collections::VecDeque;
use std::fs::File;
use std::sync::{Arc, Mutex, MutexGuard};
use std::os::fd::AsRawFd;
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
use crate::vhdx::{Result as VhdxResult, Vhdx};
use crate::AsyncAdaptor;
use crate::async_io::{
AsyncIo, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::vhdx::{Result as VhdxResult, Vhdx};
pub struct VhdxDiskSync {
vhdx_file: Arc<Mutex<Vhdx>>,
vhdx_file: Vhdx,
}
impl VhdxDiskSync {
pub fn new(f: File) -> VhdxResult<Self> {
Ok(VhdxDiskSync {
vhdx_file: Arc::new(Mutex::new(Vhdx::new(f)?)),
vhdx_file: Vhdx::new(f)?,
})
}
}
impl DiskFile for VhdxDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.vhdx_file.lock().unwrap().virtual_disk_size())
Ok(self.vhdx_file.virtual_disk_size())
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
@@ -35,16 +37,20 @@ impl DiskFile for VhdxDiskSync {
as Box<dyn AsyncIo>,
)
}
fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.vhdx_file.as_raw_fd())
}
}
pub struct VhdxSync {
vhdx_file: Arc<Mutex<Vhdx>>,
vhdx_file: Vhdx,
eventfd: EventFd,
completion_list: VecDeque<(u64, i32)>,
}
impl VhdxSync {
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>) -> std::io::Result<Self> {
pub fn new(vhdx_file: Vhdx) -> std::io::Result<Self> {
Ok(VhdxSync {
vhdx_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)?,
@@ -53,11 +59,7 @@ impl VhdxSync {
}
}
impl AsyncAdaptor<Vhdx> for Arc<Mutex<Vhdx>> {
fn file(&mut self) -> MutexGuard<Vhdx> {
self.lock().unwrap()
}
}
impl AsyncAdaptor for Vhdx {}
impl AsyncIo for VhdxSync {
fn notifier(&self) -> &EventFd {

View File

@@ -3,17 +3,25 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::env;
use std::process::Command;
fn main() {
let mut version = "v".to_owned() + env!("CARGO_PKG_VERSION");
if let Ok(git_out) = Command::new("git").args(["describe", "--dirty"]).output() {
if git_out.status.success() {
if let Ok(git_out_str) = String::from_utf8(git_out.stdout) {
version = git_out_str;
}
}
if let Ok(git_out) = Command::new("git").args(["describe", "--dirty"]).output()
&& git_out.status.success()
&& let Ok(git_out_str) = String::from_utf8(git_out.stdout)
{
version = git_out_str;
// Pop the trailing newline.
version.pop();
}
// Append CH_EXTRA_VERSION to version if it is set.
if let Ok(extra_version) = env::var("CH_EXTRA_VERSION") {
println!("cargo:rerun-if-env-changed=CH_EXTRA_VERSION");
version.push_str(&format!("-{extra_version}"));
}
// This println!() has a special behavior, as it will set the environment

View File

@@ -1,23 +1,29 @@
[package]
authors = ["The Chromium OS Authors"]
edition = "2021"
edition.workspace = true
name = "devices"
version = "0.1.0"
[dependencies]
acpi_tables = { workspace = true }
anyhow = "1.0.94"
anyhow = { workspace = true }
arch = { path = "../arch" }
bitflags = "2.6.0"
byteorder = "1.5.0"
bitfield-struct = { version = "0.12.0", optional = true }
bitflags = { workspace = true }
byteorder = { workspace = true }
event_monitor = { path = "../event_monitor" }
hypervisor = { path = "../hypervisor" }
libc = "0.2.167"
log = "0.4.22"
num_enum = "0.7.2"
libc = { workspace = true }
linux-loader = { workspace = true, features = [
"bzimage",
"elf",
"pe",
], optional = true }
log = { workspace = true }
num_enum = "0.7.4"
pci = { path = "../pci" }
serde = { version = "1.0.208", features = ["derive"] }
thiserror = "2.0.6"
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
tpm = { path = "../tpm" }
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
@@ -28,11 +34,17 @@ vm-memory = { workspace = true, features = [
] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = { workspace = true }
zerocopy = { version = "0.8.27", features = [
"alloc",
"derive",
], optional = true }
[target.'cfg(any(target_arch = "aarch64", target_arch = "riscv64"))'.dependencies]
arch = { path = "../arch" }
[features]
default = []
fw_cfg = ["arch/fw_cfg", "bitfield-struct", "linux-loader", "zerocopy"]
ivshmem = []
kvm = ["arch/kvm"]
pvmemcontrol = []

View File

@@ -8,9 +8,9 @@ use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Instant;
use acpi_tables::{aml, Aml, AmlSink};
use vm_device::interrupt::InterruptSourceGroup;
use acpi_tables::{Aml, AmlSink, aml};
use vm_device::BusDevice;
use vm_device::interrupt::InterruptSourceGroup;
use vm_memory::GuestAddress;
use vmm_sys_util::eventfd::EventFd;
@@ -51,7 +51,7 @@ impl BusDevice for AcpiShutdownDevice {
if data[0] == 1 {
info!("ACPI Reboot signalled");
if let Err(e) = self.reset_evt.write(1) {
error!("Error triggering ACPI reset event: {}", e);
error!("Error triggering ACPI reset event: {e}");
}
// Spin until we are sure the reset_evt has been handled and that when
// we return from the KVM_RUN we will exit rather than re-enter the guest.
@@ -68,7 +68,7 @@ impl BusDevice for AcpiShutdownDevice {
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
info!("ACPI Shutdown signalled");
if let Err(e) = self.exit_evt.write(1) {
error!("Error triggering ACPI shutdown event: {}", e);
error!("Error triggering ACPI shutdown event: {e}");
}
// Spin until we are sure the reset_evt has been handled and that when
// we return from the KVM_RUN we will exit rather than re-enter the guest.

View File

@@ -40,7 +40,7 @@ pub struct Aia {
impl Aia {
pub fn new(
vcpu_count: u8,
vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
vm: Arc<dyn hypervisor::Vm>,
) -> Result<Aia> {

View File

@@ -9,8 +9,8 @@ use std::sync::{Arc, Mutex};
use anyhow::anyhow;
use arch::layout;
use hypervisor::arch::aarch64::gic::{Vgic, VgicConfig};
use hypervisor::{CpuState, GicState};
use hypervisor::CpuState;
use hypervisor::arch::aarch64::gic::{GicState, Vgic, VgicConfig};
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
LegacyIrqSourceConfig, MsiIrqGroupConfig,
@@ -39,7 +39,7 @@ pub struct Gic {
impl Gic {
pub fn new(
vcpu_count: u8,
vcpu_count: u32,
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
vm: Arc<dyn hypervisor::Vm>,
) -> Result<Gic> {

View File

@@ -17,39 +17,39 @@ pub enum Error {
#[error("Invalid delivery mode")]
InvalidDeliveryMode,
/// Failed creating the interrupt source group.
#[error("Failed creating the interrupt source group: {0}")]
CreateInterruptSourceGroup(io::Error),
#[error("Failed creating the interrupt source group")]
CreateInterruptSourceGroup(#[source] io::Error),
/// Failed triggering the interrupt.
#[error("Failed triggering the interrupt: {0}")]
TriggerInterrupt(io::Error),
#[error("Failed triggering the interrupt")]
TriggerInterrupt(#[source] io::Error),
/// Failed masking the interrupt.
#[error("Failed masking the interrupt: {0}")]
MaskInterrupt(io::Error),
#[error("Failed masking the interrupt")]
MaskInterrupt(#[source] io::Error),
/// Failed unmasking the interrupt.
#[error("Failed unmasking the interrupt: {0}")]
UnmaskInterrupt(io::Error),
#[error("Failed unmasking the interrupt")]
UnmaskInterrupt(#[source] io::Error),
/// Failed updating the interrupt.
#[error("Failed updating the interrupt: {0}")]
UpdateInterrupt(io::Error),
#[error("Failed updating the interrupt")]
UpdateInterrupt(#[source] io::Error),
/// Failed enabling the interrupt.
#[error("Failed enabling the interrupt: {0}")]
EnableInterrupt(io::Error),
#[error("Failed enabling the interrupt")]
EnableInterrupt(#[source] io::Error),
#[cfg(target_arch = "aarch64")]
/// Failed creating GIC device.
#[error("Failed creating GIC device: {0}")]
CreateGic(hypervisor::HypervisorVmError),
#[error("Failed creating GIC device")]
CreateGic(#[source] hypervisor::HypervisorVmError),
#[cfg(target_arch = "aarch64")]
/// Failed restoring GIC device.
#[error("Failed restoring GIC device: {0}")]
RestoreGic(hypervisor::arch::aarch64::gic::Error),
#[error("Failed restoring GIC device")]
RestoreGic(#[source] hypervisor::arch::aarch64::gic::Error),
#[cfg(target_arch = "riscv64")]
/// Failed creating AIA device.
#[error("Failed creating AIA device: {0}")]
CreateAia(hypervisor::HypervisorVmError),
#[error("Failed creating AIA device")]
CreateAia(#[source] hypervisor::HypervisorVmError),
#[cfg(target_arch = "riscv64")]
/// Failed restoring AIA device.
#[error("Failed restoring AIA device: {0}")]
RestoreAia(hypervisor::arch::riscv64::aia::Error),
#[error("Failed restoring AIA device")]
RestoreAia(#[source] hypervisor::arch::riscv64::aia::Error),
}
type Result<T> = result::Result<T, Error>;

View File

@@ -14,11 +14,11 @@ use std::sync::{Arc, Barrier};
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use vm_device::BusDevice;
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
MsiIrqGroupConfig, MsiIrqSourceConfig,
};
use vm_device::BusDevice;
use vm_memory::GuestAddress;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
@@ -151,13 +151,13 @@ impl BusDevice for Ioapic {
return;
}
debug!("IOAPIC_R @ offset 0x{:x}", offset);
debug!("IOAPIC_R @ offset 0x{offset:x}");
let value: u32 = match offset as u8 {
IOREGSEL_OFF => self.reg_sel,
IOWIN_OFF => self.ioapic_read(),
_ => {
error!("IOAPIC: failed reading at offset {}", offset);
error!("IOAPIC: failed reading at offset {offset}");
return;
}
};
@@ -171,7 +171,7 @@ impl BusDevice for Ioapic {
return None;
}
debug!("IOAPIC_W @ offset 0x{:x}", offset);
debug!("IOAPIC_W @ offset 0x{offset:x}");
let value = LittleEndian::read_u32(data);
@@ -179,7 +179,7 @@ impl BusDevice for Ioapic {
IOREGSEL_OFF => self.reg_sel = value,
IOWIN_OFF => self.ioapic_write(value),
_ => {
error!("IOAPIC: failed writing at offset {}", offset);
error!("IOAPIC: failed writing at offset {offset}");
}
}
None
@@ -266,7 +266,7 @@ impl Ioapic {
IOWIN_OFF..=REG_MAX_OFFSET => {
let (index, is_high_bits) = decode_irq_from_selector(self.reg_sel as u8);
if index > NUM_IOAPIC_PINS {
warn!("IOAPIC index out of range: {}", index);
warn!("IOAPIC index out of range: {index}");
return;
}
if is_high_bits {
@@ -282,7 +282,7 @@ impl Ioapic {
// The entry must be updated through the interrupt source
// group.
if let Err(e) = self.update_entry(index, true) {
error!("Failed updating IOAPIC entry: {:?}", e);
error!("Failed updating IOAPIC entry: {e:?}");
}
// Store the information this IRQ is now being used.
self.used_entries[index] = true;
@@ -303,7 +303,7 @@ impl Ioapic {
IOWIN_OFF..=REG_MAX_OFFSET => {
let (index, is_high_bits) = decode_irq_from_selector(self.reg_sel as u8);
if index > NUM_IOAPIC_PINS {
warn!("IOAPIC index out of range: {}", index);
warn!("IOAPIC index out of range: {index}");
return 0;
}
if is_high_bits {
@@ -418,7 +418,7 @@ impl InterruptController for Ioapic {
self.interrupt_source_group
.trigger(irq as InterruptIndex)
.map_err(Error::TriggerInterrupt)?;
debug!("Interrupt {irq} successfully delivered");
trace!("Interrupt {irq} successfully delivered");
// If trigger mode is level sensitive, set the Remote IRR bit.
// It will be cleared when the EOI is received.

420
devices/src/ivshmem.rs Normal file
View File

@@ -0,0 +1,420 @@
// Copyright © 2024 Tencent Corporation. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
use std::any::Any;
use std::path::PathBuf;
use std::result;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, Barrier, Mutex};
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use pci::{
BarReprogrammingParams, PCI_CONFIGURATION_ID, PciBarConfiguration, PciBarPrefetchable,
PciBarRegionType, PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType,
PciSubclass,
};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::{BusDevice, Resource, UserspaceMapping};
use vm_memory::bitmap::AtomicBitmap;
use vm_memory::{Address, GuestAddress};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
const IVSHMEM_BAR0_IDX: usize = 0;
const IVSHMEM_BAR1_IDX: usize = 1;
const IVSHMEM_BAR2_IDX: usize = 2;
const IVSHMEM_VENDOR_ID: u16 = 0x1af4;
const IVSHMEM_DEVICE_ID: u16 = 0x1110;
const IVSHMEM_REG_BAR_SIZE: u64 = 0x100;
type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>;
#[derive(Debug, Error)]
pub enum IvshmemError {
#[error("Failed to retrieve PciConfigurationState: {0}")]
RetrievePciConfigurationState(#[source] anyhow::Error),
#[error("Failed to retrieve IvshmemDeviceState: {0}")]
RetrieveIvshmemDeviceStateState(#[source] anyhow::Error),
#[error("Failed to remove user memory region")]
RemoveUserMemoryRegion,
#[error("Failed to create user memory region.")]
CreateUserMemoryRegion,
#[error("Failed to create userspace mapping.")]
CreateUserspaceMapping,
#[error("Failed to remove old userspace mapping.")]
RemoveUserspaceMapping,
}
#[derive(Copy, Clone)]
pub enum IvshmemSubclass {
Other = 0x00,
}
impl PciSubclass for IvshmemSubclass {
fn get_register_value(&self) -> u8 {
*self as u8
}
}
pub trait IvshmemOps: Send + Sync {
fn map_ram_region(
&mut self,
start_addr: u64,
size: usize,
backing_file: Option<PathBuf>,
) -> Result<(Arc<GuestRegionMmap>, UserspaceMapping), IvshmemError>;
fn unmap_ram_region(&mut self, mapping: UserspaceMapping) -> Result<(), IvshmemError>;
}
/// Inner-Vm Shared Memory Device (Ivshmem device)
///
/// This device can share memory between host and guest(ivshmem-plain)
/// and share memory between guests(ivshmem-doorbell).
/// But only ivshmem-plain support now, ivshmem-doorbell doesn't support yet.
pub struct IvshmemDevice {
id: String,
// ivshmem device registers
// (only used for ivshmem-doorbell, ivshmem-doorbell don't support yet)
_interrupt_mask: u32,
_interrupt_status: Arc<AtomicU32>,
_iv_position: u32,
_doorbell: u32,
// PCI configuration registers.
configuration: PciConfiguration,
bar_regions: Vec<PciBarConfiguration>,
region_size: u64,
ivshmem_ops: Arc<Mutex<dyn IvshmemOps>>,
backend_file: Option<PathBuf>,
region: Option<Arc<GuestRegionMmap>>,
userspace_mapping: Option<UserspaceMapping>,
}
#[derive(Serialize, Deserialize, Default, Clone)]
pub struct IvshmemDeviceState {
interrupt_mask: u32,
interrupt_status: u32,
iv_position: u32,
doorbell: u32,
}
impl IvshmemDevice {
pub fn new(
id: String,
region_size: u64,
backend_file: Option<PathBuf>,
ivshmem_ops: Arc<Mutex<dyn IvshmemOps>>,
snapshot: Option<Snapshot>,
) -> Result<Self, IvshmemError> {
let pci_configuration_state =
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
IvshmemError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {e}",
))
})?;
let state: Option<IvshmemDeviceState> = snapshot
.as_ref()
.map(|s| s.to_state())
.transpose()
.map_err(|e| {
IvshmemError::RetrieveIvshmemDeviceStateState(anyhow!(
"Failed to get IvshmemDeviceState from Snapshot: {e}",
))
})?;
let configuration = PciConfiguration::new(
IVSHMEM_VENDOR_ID,
IVSHMEM_DEVICE_ID,
0x1,
PciClassCode::MemoryController,
&IvshmemSubclass::Other,
None,
PciHeaderType::Device,
0,
0,
None,
pci_configuration_state,
);
let device = if let Some(s) = state {
IvshmemDevice {
id,
configuration,
bar_regions: vec![],
_interrupt_mask: s.interrupt_mask,
_interrupt_status: Arc::new(AtomicU32::new(s.interrupt_status)),
_iv_position: s.iv_position,
_doorbell: s.doorbell,
region_size,
ivshmem_ops,
region: None,
userspace_mapping: None,
backend_file,
}
} else {
IvshmemDevice {
id,
configuration,
bar_regions: vec![],
_interrupt_mask: 0,
_interrupt_status: Arc::new(AtomicU32::new(0)),
_iv_position: 0,
_doorbell: 0,
region_size,
ivshmem_ops,
region: None,
userspace_mapping: None,
backend_file,
}
};
Ok(device)
}
pub fn set_region(
&mut self,
region: Arc<GuestRegionMmap>,
userspace_mapping: UserspaceMapping,
) {
self.region = Some(region);
self.userspace_mapping = Some(userspace_mapping);
}
pub fn config_bar_addr(&self) -> u64 {
self.configuration.get_bar_addr(IVSHMEM_BAR0_IDX)
}
pub fn data_bar_addr(&self) -> u64 {
self.configuration.get_bar_addr(IVSHMEM_BAR2_IDX)
}
fn state(&self) -> IvshmemDeviceState {
IvshmemDeviceState {
interrupt_mask: self._interrupt_mask,
interrupt_status: self._interrupt_status.load(Ordering::SeqCst),
iv_position: self._iv_position,
doorbell: self._doorbell,
}
}
}
impl BusDevice for IvshmemDevice {
fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {
self.read_bar(base, offset, data)
}
fn write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
self.write_bar(base, offset, data)
}
}
impl PciDevice for IvshmemDevice {
fn allocate_bars(
&mut self,
_allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new();
let mut bar0_addr = None;
let mut bar2_addr = None;
let restoring = resources.is_some();
if let Some(resources) = resources {
for resource in resources {
match resource {
Resource::PciBar { index, base, .. } => {
match index {
IVSHMEM_BAR0_IDX => {
bar0_addr = Some(GuestAddress(base));
}
IVSHMEM_BAR1_IDX => {}
IVSHMEM_BAR2_IDX => {
bar2_addr = Some(GuestAddress(base));
}
_ => {
error!("Unexpected pci bar index {index}");
}
};
}
_ => {
error!("Unexpected resource {resource:?}");
}
}
}
if bar0_addr.is_none() || bar2_addr.is_none() {
return Err(PciDeviceError::MissingResource);
}
}
// BAR0 holds device registers (256 Byte MMIO)
let bar0_addr = mmio32_allocator
.allocate(bar0_addr, IVSHMEM_REG_BAR_SIZE, None)
.ok_or(PciDeviceError::IoAllocationFailed(IVSHMEM_REG_BAR_SIZE))?;
debug!("ivshmem bar0 address 0x{:x}", bar0_addr.0);
let bar0 = PciBarConfiguration::default()
.set_index(IVSHMEM_BAR0_IDX)
.set_address(bar0_addr.raw_value())
.set_size(IVSHMEM_REG_BAR_SIZE)
.set_region_type(PciBarRegionType::Memory32BitRegion)
.set_prefetchable(PciBarPrefetchable::NotPrefetchable);
// BAR1 holds MSI-X table and PBA (only ivshmem-doorbell).
// BAR2 maps the shared memory object
let bar2_size = self.region_size;
let bar2_addr = mmio64_allocator
.allocate(bar2_addr, bar2_size, None)
.ok_or(PciDeviceError::IoAllocationFailed(bar2_size))?;
debug!("ivshmem bar2 address 0x{:x}", bar2_addr.0);
let bar2 = PciBarConfiguration::default()
.set_index(IVSHMEM_BAR2_IDX)
.set_address(bar2_addr.raw_value())
.set_size(bar2_size)
.set_region_type(PciBarRegionType::Memory64BitRegion)
.set_prefetchable(PciBarPrefetchable::Prefetchable);
if !restoring {
self.configuration
.add_pci_bar(&bar0)
.map_err(|e| PciDeviceError::IoRegistrationFailed(bar0_addr.raw_value(), e))?;
self.configuration
.add_pci_bar(&bar2)
.map_err(|e| PciDeviceError::IoRegistrationFailed(bar2_addr.raw_value(), e))?;
}
bars.push(bar0);
bars.push(bar2);
self.bar_regions = bars.clone();
Ok(bars)
}
fn free_bars(
&mut self,
_allocator: &mut SystemAllocator,
_mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> {
unimplemented!("Device hotplug and remove are not supported for ivshmem");
}
fn write_config_register(
&mut self,
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Vec<BarReprogrammingParams>, 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_reg(reg_idx)
}
fn read_bar(&mut self, base: u64, offset: u64, data: &mut [u8]) {
debug!("read base {base:x} offset {offset}");
let mut bar_idx = 0;
for (idx, bar) in self.bar_regions.iter().enumerate() {
if bar.addr() == base {
bar_idx = idx;
}
}
match bar_idx {
// bar 0
0 => {
// ivshmem don't use interrupt, we return zero now.
LittleEndian::write_u32(data, 0);
}
// bar 2
1 => warn!("Unexpected read ivshmem memory idx: {offset}"),
_ => {
warn!("Invalid bar_idx: {bar_idx}");
}
};
}
fn write_bar(&mut self, base: u64, offset: u64, _data: &[u8]) -> Option<Arc<Barrier>> {
debug!("write base {base:x} offset {offset}");
warn!("Unexpected write ivshmem memory idx: {offset}");
None
}
fn move_bar(&mut self, old_base: u64, new_base: u64) -> result::Result<(), std::io::Error> {
if new_base == self.data_bar_addr() {
if let Some(old_mapping) = self.userspace_mapping.take() {
self.ivshmem_ops
.lock()
.unwrap()
.unmap_ram_region(old_mapping)
.map_err(std::io::Error::other)?;
}
let (region, new_mapping) = self
.ivshmem_ops
.lock()
.unwrap()
.map_ram_region(
new_base,
self.region_size as usize,
self.backend_file.clone(),
)
.map_err(std::io::Error::other)?;
self.set_region(region, new_mapping);
}
for bar in self.bar_regions.iter_mut() {
if bar.addr() == old_base {
*bar = bar.set_address(new_base);
}
}
Ok(())
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn id(&self) -> Option<String> {
Some(self.id.clone())
}
}
impl Pausable for IvshmemDevice {}
impl Snapshottable for IvshmemDevice {
fn id(&self) -> String {
self.id.clone()
}
// The snapshot/restore (also live migration) support only work for ivshmem-plain mode.
// Additional work is needed for supporting ivshmem-doorbell.
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let mut snapshot = Snapshot::new_from_state(&self.state())?;
// Snapshot PciConfiguration
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
Ok(snapshot)
}
}
impl Transportable for IvshmemDevice {}
impl Migratable for IvshmemDevice {}

View File

@@ -12,7 +12,7 @@ use std::{mem, thread};
// https://github.com/rust-lang/libc/issues/1848
#[cfg_attr(target_env = "musl", allow(deprecated))]
use libc::time_t;
use libc::{clock_gettime, gmtime_r, timespec, tm, CLOCK_REALTIME};
use libc::{CLOCK_REALTIME, clock_gettime, gmtime_r, timespec, tm};
use vm_device::BusDevice;
use vmm_sys_util::eventfd::EventFd;
@@ -90,7 +90,7 @@ impl BusDevice for Cmos {
self.data[(self.index & INDEX_MASK) as usize] = data[0]
}
}
o => warn!("bad write offset on CMOS device: {}", o),
o => warn!("bad write offset on CMOS device: {o}"),
};
None
}
@@ -164,7 +164,7 @@ impl BusDevice for Cmos {
}
}
o => {
warn!("bad read offset on CMOS device: {}", o);
warn!("bad read offset on CMOS device: {o}");
0
}
}

View File

@@ -0,0 +1,954 @@
// Copyright 2025 Google LLC.
//
// SPDX-License-Identifier: Apache-2.0
//
/// Cloud Hypervisor implementation of Qemu's fw_cfg spec
/// https://www.qemu.org/docs/master/specs/fw_cfg.html
/// Linux kernel fw_cfg driver header
/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/qemu_fw_cfg.h
/// Uploading files to the guest via fw_cfg is supported for all kernels 4.6+ w/ CONFIG_FW_CFG_SYSFS enabled
/// https://cateee.net/lkddb/web-lkddb/FW_CFG_SYSFS.html
/// No kernel requirement if above functionality is not required,
/// only firmware must implement mechanism to interact with this fw_cfg device
use std::{
fs::File,
io::{ErrorKind, Read, Result, Seek, SeekFrom},
mem::offset_of,
os::unix::fs::FileExt,
sync::{Arc, Barrier},
};
use acpi_tables::rsdp::Rsdp;
use arch::RegionType;
#[cfg(target_arch = "aarch64")]
use arch::aarch64::layout::{
MEM_32BIT_DEVICES_START, MEM_32BIT_RESERVED_START, RAM_64BIT_START, RAM_START as HIGH_RAM_START,
};
#[cfg(target_arch = "x86_64")]
use arch::layout::{
EBDA_START, HIGH_RAM_START, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START,
MEM_32BIT_RESERVED_START, PCI_MMCONFIG_SIZE, PCI_MMCONFIG_START, RAM_64BIT_START,
};
use bitfield_struct::bitfield;
#[cfg(target_arch = "x86_64")]
use linux_loader::bootparam::boot_params;
#[cfg(target_arch = "aarch64")]
use linux_loader::loader::pe::arm64_image_header as boot_params;
use vm_device::BusDevice;
use vm_memory::bitmap::AtomicBitmap;
use vm_memory::{
ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap,
};
use vmm_sys_util::sock_ctrl_msg::IntoIovec;
use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes};
#[cfg(target_arch = "x86_64")]
// https://github.com/project-oak/oak/tree/main/stage0_bin#memory-layout
const STAGE0_START_ADDRESS: GuestAddress = GuestAddress(0xfffe_0000);
#[cfg(target_arch = "x86_64")]
const STAGE0_SIZE: usize = 0x2_0000;
const E820_RAM: u32 = 1;
const E820_RESERVED: u32 = 2;
#[cfg(target_arch = "x86_64")]
const PORT_FW_CFG_SELECTOR: u64 = 0x510;
#[cfg(target_arch = "x86_64")]
const PORT_FW_CFG_DATA: u64 = 0x511;
#[cfg(target_arch = "x86_64")]
const PORT_FW_CFG_DMA_HI: u64 = 0x514;
#[cfg(target_arch = "x86_64")]
const PORT_FW_CFG_DMA_LO: u64 = 0x518;
#[cfg(target_arch = "x86_64")]
pub const PORT_FW_CFG_BASE: u64 = 0x510;
#[cfg(target_arch = "x86_64")]
pub const PORT_FW_CFG_WIDTH: u64 = 0xc;
#[cfg(target_arch = "aarch64")]
const PORT_FW_CFG_SELECTOR: u64 = 0x9030008;
#[cfg(target_arch = "aarch64")]
const PORT_FW_CFG_DATA: u64 = 0x9030000;
#[cfg(target_arch = "aarch64")]
const PORT_FW_CFG_DMA_HI: u64 = 0x9030010;
#[cfg(target_arch = "aarch64")]
const PORT_FW_CFG_DMA_LO: u64 = 0x9030014;
#[cfg(target_arch = "aarch64")]
pub const PORT_FW_CFG_BASE: u64 = 0x9030000;
#[cfg(target_arch = "aarch64")]
pub const PORT_FW_CFG_WIDTH: u64 = 0x10;
const FW_CFG_SIGNATURE: u16 = 0x00;
const FW_CFG_ID: u16 = 0x01;
const FW_CFG_KERNEL_SIZE: u16 = 0x08;
const FW_CFG_INITRD_SIZE: u16 = 0x0b;
const FW_CFG_KERNEL_DATA: u16 = 0x11;
const FW_CFG_INITRD_DATA: u16 = 0x12;
const FW_CFG_CMDLINE_SIZE: u16 = 0x14;
const FW_CFG_CMDLINE_DATA: u16 = 0x15;
const FW_CFG_SETUP_SIZE: u16 = 0x17;
const FW_CFG_SETUP_DATA: u16 = 0x18;
const FW_CFG_FILE_DIR: u16 = 0x19;
const FW_CFG_KNOWN_ITEMS: usize = 0x20;
pub const FW_CFG_FILE_FIRST: u16 = 0x20;
pub const FW_CFG_DMA_SIGNATURE: [u8; 8] = *b"QEMU CFG";
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/qemu_fw_cfg.h
pub const FW_CFG_ACPI_ID: &str = "QEMU0002";
// Reserved (must be enabled)
const FW_CFG_F_RESERVED: u8 = 1 << 0;
// DMA Toggle Bit (enabled by default)
const FW_CFG_F_DMA: u8 = 1 << 1;
pub const FW_CFG_FEATURE: [u8; 4] = [FW_CFG_F_RESERVED | FW_CFG_F_DMA, 0, 0, 0];
const COMMAND_ALLOCATE: u32 = 0x1;
const COMMAND_ADD_POINTER: u32 = 0x2;
const COMMAND_ADD_CHECKSUM: u32 = 0x3;
const ALLOC_ZONE_HIGH: u8 = 0x1;
const ALLOC_ZONE_FSEG: u8 = 0x2;
const FW_CFG_FILENAME_TABLE_LOADER: &str = "etc/table-loader";
const FW_CFG_FILENAME_RSDP: &str = "acpi/rsdp";
const FW_CFG_FILENAME_ACPI_TABLES: &str = "acpi/tables";
#[derive(Debug)]
pub enum FwCfgContent {
Bytes(Vec<u8>),
Slice(&'static [u8]),
File(u64, File),
U32(u32),
}
struct FwCfgContentAccess<'a> {
content: &'a FwCfgContent,
offset: u32,
}
impl Read for FwCfgContentAccess<'_> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
match self.content {
FwCfgContent::File(offset, f) => {
Seek::seek(&mut (&*f), SeekFrom::Start(offset + self.offset as u64))?;
Read::read(&mut (&*f), buf)
}
FwCfgContent::Bytes(b) => match b.get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
FwCfgContent::Slice(b) => match b.get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
FwCfgContent::U32(n) => match n.to_le_bytes().get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
}
}
}
impl Default for FwCfgContent {
fn default() -> Self {
FwCfgContent::Slice(&[])
}
}
impl FwCfgContent {
fn size(&self) -> Result<u32> {
let ret = match self {
FwCfgContent::Bytes(v) => v.len(),
FwCfgContent::File(offset, f) => (f.metadata()?.len() - offset) as usize,
FwCfgContent::Slice(s) => s.len(),
FwCfgContent::U32(n) => size_of_val(n),
};
u32::try_from(ret).map_err(|_| std::io::ErrorKind::InvalidInput.into())
}
fn access(&self, offset: u32) -> FwCfgContentAccess<'_> {
FwCfgContentAccess {
content: self,
offset,
}
}
}
#[derive(Debug, Default)]
pub struct FwCfgItem {
pub name: String,
pub content: FwCfgContent,
}
/// https://www.qemu.org/docs/master/specs/fw_cfg.html
#[derive(Debug)]
pub struct FwCfg {
selector: u16,
data_offset: u32,
dma_address: u64,
items: Vec<FwCfgItem>, // 0x20 and above
known_items: [FwCfgContent; FW_CFG_KNOWN_ITEMS], // 0x0 to 0x19
memory: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
}
#[repr(C)]
#[derive(Debug, IntoBytes, FromBytes)]
struct FwCfgDmaAccess {
control_be: u32,
length_be: u32,
address_be: u64,
}
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/qemu_fw_cfg.h#L67
#[bitfield(u32)]
struct AccessControl {
// FW_CFG_DMA_CTL_ERROR = 0x01
error: bool,
// FW_CFG_DMA_CTL_READ = 0x02
read: bool,
#[bits(1)]
_unused2: u8,
// FW_CFG_DMA_CTL_SKIP = 0x04
skip: bool,
#[bits(3)]
_unused3: u8,
// FW_CFG_DMA_CTL_ERROR = 0x08
select: bool,
#[bits(7)]
_unused4: u8,
// FW_CFG_DMA_CTL_WRITE = 0x10
write: bool,
#[bits(16)]
_unused: u32,
}
#[repr(C)]
#[derive(Debug, IntoBytes, FromBytes)]
struct FwCfgFilesHeader {
count_be: u32,
}
pub const FILE_NAME_SIZE: usize = 56;
pub fn create_file_name(name: &str) -> [u8; FILE_NAME_SIZE] {
let mut c_name = [0u8; FILE_NAME_SIZE];
let c_len = std::cmp::min(FILE_NAME_SIZE - 1, name.len());
c_name[0..c_len].copy_from_slice(&name.as_bytes()[0..c_len]);
c_name
}
#[allow(dead_code)]
#[repr(C, packed)]
#[derive(Debug, IntoBytes, FromBytes, Clone, Copy)]
struct BootE820Entry {
addr: u64,
size: u64,
type_: u32,
}
#[repr(C)]
#[derive(Debug, IntoBytes, FromBytes)]
struct FwCfgFile {
size_be: u32,
select_be: u16,
_reserved: u16,
name: [u8; FILE_NAME_SIZE],
}
#[repr(C, align(4))]
#[derive(Debug, IntoBytes, Immutable)]
struct Allocate {
command: u32,
file: [u8; FILE_NAME_SIZE],
align: u32,
zone: u8,
_pad: [u8; 63],
}
#[repr(C, align(4))]
#[derive(Debug, IntoBytes, Immutable)]
struct AddPointer {
command: u32,
dst: [u8; FILE_NAME_SIZE],
src: [u8; FILE_NAME_SIZE],
offset: u32,
size: u8,
_pad: [u8; 7],
}
#[repr(C, align(4))]
#[derive(Debug, IntoBytes, Immutable)]
struct AddChecksum {
command: u32,
file: [u8; FILE_NAME_SIZE],
offset: u32,
start: u32,
len: u32,
_pad: [u8; 56],
}
fn create_intra_pointer(name: &str, offset: usize, size: u8) -> AddPointer {
AddPointer {
command: COMMAND_ADD_POINTER,
dst: create_file_name(name),
src: create_file_name(name),
offset: offset as u32,
size,
_pad: [0; 7],
}
}
fn create_acpi_table_checksum(offset: usize, len: usize) -> AddChecksum {
AddChecksum {
command: COMMAND_ADD_CHECKSUM,
file: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
offset: (offset + offset_of!(AcpiTableHeader, checksum)) as u32,
start: offset as u32,
len: len as u32,
_pad: [0; 56],
}
}
#[repr(C, align(4))]
#[derive(Debug, Clone, Default, FromBytes, IntoBytes)]
struct AcpiTableHeader {
signature: [u8; 4],
length: u32,
revision: u8,
checksum: u8,
oem_id: [u8; 6],
oem_table_id: [u8; 8],
oem_revision: u32,
asl_compiler_id: [u8; 4],
asl_compiler_revision: u32,
}
struct AcpiTable {
rsdp: Rsdp,
tables: Vec<u8>,
table_pointers: Vec<usize>,
table_checksums: Vec<(usize, usize)>,
}
impl AcpiTable {
fn pointers(&self) -> &[usize] {
&self.table_pointers
}
fn checksums(&self) -> &[(usize, usize)] {
&self.table_checksums
}
fn take(self) -> (Rsdp, Vec<u8>) {
(self.rsdp, self.tables)
}
}
// Creates fw_cfg items used by firmware to load and verify Acpi tables
// https://github.com/qemu/qemu/blob/master/hw/acpi/bios-linker-loader.c
fn create_acpi_loader(acpi_table: AcpiTable) -> [FwCfgItem; 3] {
let mut table_loader_bytes: Vec<u8> = Vec::new();
let allocate_rsdp = Allocate {
command: COMMAND_ALLOCATE,
file: create_file_name(FW_CFG_FILENAME_RSDP),
align: 4,
zone: ALLOC_ZONE_FSEG,
_pad: [0; 63],
};
table_loader_bytes.extend(allocate_rsdp.as_bytes());
let allocate_tables = Allocate {
command: COMMAND_ALLOCATE,
file: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
align: 4,
zone: ALLOC_ZONE_HIGH,
_pad: [0; 63],
};
table_loader_bytes.extend(allocate_tables.as_bytes());
for pointer_offset in acpi_table.pointers().iter() {
let pointer = create_intra_pointer(FW_CFG_FILENAME_ACPI_TABLES, *pointer_offset, 8);
table_loader_bytes.extend(pointer.as_bytes());
}
for (offset, len) in acpi_table.checksums().iter() {
let checksum = create_acpi_table_checksum(*offset, *len);
table_loader_bytes.extend(checksum.as_bytes());
}
let pointer_rsdp_to_xsdt = AddPointer {
command: COMMAND_ADD_POINTER,
dst: create_file_name(FW_CFG_FILENAME_RSDP),
src: create_file_name(FW_CFG_FILENAME_ACPI_TABLES),
offset: offset_of!(Rsdp, xsdt_addr) as u32,
size: 8,
_pad: [0; 7],
};
table_loader_bytes.extend(pointer_rsdp_to_xsdt.as_bytes());
let checksum_rsdp = AddChecksum {
command: COMMAND_ADD_CHECKSUM,
file: create_file_name(FW_CFG_FILENAME_RSDP),
offset: offset_of!(Rsdp, checksum) as u32,
start: 0,
len: offset_of!(Rsdp, length) as u32,
_pad: [0; 56],
};
let checksum_rsdp_ext = AddChecksum {
command: COMMAND_ADD_CHECKSUM,
file: create_file_name(FW_CFG_FILENAME_RSDP),
offset: offset_of!(Rsdp, extended_checksum) as u32,
start: 0,
len: size_of::<Rsdp>() as u32,
_pad: [0; 56],
};
table_loader_bytes.extend(checksum_rsdp.as_bytes());
table_loader_bytes.extend(checksum_rsdp_ext.as_bytes());
let table_loader = FwCfgItem {
name: FW_CFG_FILENAME_TABLE_LOADER.to_owned(),
content: FwCfgContent::Bytes(table_loader_bytes),
};
let (rsdp, tables) = acpi_table.take();
let acpi_rsdp = FwCfgItem {
name: FW_CFG_FILENAME_RSDP.to_owned(),
content: FwCfgContent::Bytes(rsdp.as_bytes().to_owned()),
};
let apci_tables = FwCfgItem {
name: FW_CFG_FILENAME_ACPI_TABLES.to_owned(),
content: FwCfgContent::Bytes(tables),
};
[table_loader, acpi_rsdp, apci_tables]
}
impl FwCfg {
pub fn new(memory: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>) -> FwCfg {
const DEFAULT_ITEM: FwCfgContent = FwCfgContent::Slice(&[]);
let mut known_items = [DEFAULT_ITEM; FW_CFG_KNOWN_ITEMS];
known_items[FW_CFG_SIGNATURE as usize] = FwCfgContent::Slice(&FW_CFG_DMA_SIGNATURE);
known_items[FW_CFG_ID as usize] = FwCfgContent::Slice(&FW_CFG_FEATURE);
let file_buf = Vec::from(FwCfgFilesHeader { count_be: 0 }.as_mut_bytes());
known_items[FW_CFG_FILE_DIR as usize] = FwCfgContent::Bytes(file_buf);
FwCfg {
selector: 0,
data_offset: 0,
dma_address: 0,
items: vec![],
known_items,
memory,
}
}
pub fn populate_fw_cfg(
&mut self,
mem_size: Option<usize>,
kernel: Option<File>,
initramfs: Option<File>,
cmdline: Option<std::ffi::CString>,
fw_cfg_item_list: Option<Vec<FwCfgItem>>,
) -> Result<()> {
if let Some(mem_size) = mem_size {
self.add_e820(mem_size)?
}
if let Some(kernel) = kernel {
self.add_kernel_data(&kernel)?;
}
if let Some(cmdline) = cmdline {
self.add_kernel_cmdline(cmdline);
}
if let Some(initramfs) = initramfs {
self.add_initramfs_data(&initramfs)?
}
if let Some(fw_cfg_item_list) = fw_cfg_item_list {
for item in fw_cfg_item_list {
self.add_item(item)?;
}
}
Ok(())
}
pub fn add_e820(&mut self, mem_size: usize) -> Result<()> {
#[cfg(target_arch = "x86_64")]
let mut mem_regions = vec![
(GuestAddress(0), EBDA_START.0 as usize, RegionType::Ram),
(
MEM_32BIT_DEVICES_START,
MEM_32BIT_DEVICES_SIZE as usize,
RegionType::Reserved,
),
(
PCI_MMCONFIG_START,
PCI_MMCONFIG_SIZE as usize,
RegionType::Reserved,
),
(STAGE0_START_ADDRESS, STAGE0_SIZE, RegionType::Reserved),
];
#[cfg(target_arch = "aarch64")]
let mut mem_regions = arch::aarch64::arch_memory_regions();
if mem_size < MEM_32BIT_DEVICES_START.0 as usize {
mem_regions.push((
HIGH_RAM_START,
mem_size - HIGH_RAM_START.0 as usize,
RegionType::Ram,
));
} else {
mem_regions.push((
HIGH_RAM_START,
MEM_32BIT_RESERVED_START.0 as usize - HIGH_RAM_START.0 as usize,
RegionType::Ram,
));
mem_regions.push((
RAM_64BIT_START,
mem_size - (MEM_32BIT_DEVICES_START.0 as usize),
RegionType::Ram,
));
}
let mut bytes = vec![];
for (addr, size, region) in mem_regions.iter() {
let type_ = match region {
RegionType::Ram => E820_RAM,
RegionType::Reserved => E820_RESERVED,
RegionType::SubRegion => continue,
};
let mut entry = BootE820Entry {
addr: addr.0,
size: *size as u64,
type_,
};
bytes.extend_from_slice(entry.as_mut_bytes());
}
let item = FwCfgItem {
name: "etc/e820".to_owned(),
content: FwCfgContent::Bytes(bytes),
};
self.add_item(item)
}
fn file_dir_mut(&mut self) -> &mut Vec<u8> {
let FwCfgContent::Bytes(file_buf) = &mut self.known_items[FW_CFG_FILE_DIR as usize] else {
unreachable!("fw_cfg: selector {FW_CFG_FILE_DIR:#x} should be FwCfgContent::Byte!")
};
file_buf
}
fn update_count(&mut self) {
let mut header = FwCfgFilesHeader {
count_be: (self.items.len() as u32).to_be(),
};
self.file_dir_mut()[0..4].copy_from_slice(header.as_mut_bytes());
}
pub fn add_item(&mut self, item: FwCfgItem) -> Result<()> {
let index = self.items.len();
let c_name = create_file_name(&item.name);
let size = item.content.size()?;
let mut cfg_file = FwCfgFile {
size_be: size.to_be(),
select_be: (FW_CFG_FILE_FIRST + index as u16).to_be(),
_reserved: 0,
name: c_name,
};
self.file_dir_mut()
.extend_from_slice(cfg_file.as_mut_bytes());
self.items.push(item);
self.update_count();
Ok(())
}
fn dma_read_content(
&self,
content: &FwCfgContent,
offset: u32,
len: u32,
address: u64,
) -> Result<u32> {
let content_size = content.size()?.saturating_sub(offset);
let op_size = std::cmp::min(content_size, len);
let mut access = content.access(offset);
let mut buf = vec![0u8; op_size as usize];
access.read_exact(buf.as_mut_bytes())?;
let r = self
.memory
.memory()
.write(buf.as_bytes(), GuestAddress(address));
match r {
Err(e) => {
error!("fw_cfg: dma read error: {e:x?}");
Err(ErrorKind::InvalidInput.into())
}
Ok(size) => Ok(size as u32),
}
}
fn dma_read(&mut self, selector: u16, len: u32, address: u64) -> Result<()> {
let op_size = if let Some(content) = self.known_items.get(selector as usize) {
self.dma_read_content(content, self.data_offset, len, address)
} else if let Some(item) = self.items.get((selector - FW_CFG_FILE_FIRST) as usize) {
self.dma_read_content(&item.content, self.data_offset, len, address)
} else {
error!("fw_cfg: selector {selector:#x} does not exist.");
Err(ErrorKind::NotFound.into())
}?;
self.data_offset += op_size;
Ok(())
}
fn do_dma(&mut self) {
let dma_address = self.dma_address;
let mut access = FwCfgDmaAccess::new_zeroed();
let dma_access = match self
.memory
.memory()
.read(access.as_mut_bytes(), GuestAddress(dma_address))
{
Ok(_) => access,
Err(e) => {
error!("fw_cfg: invalid address of dma access {dma_address:#x}: {e:?}");
return;
}
};
let control = AccessControl(u32::from_be(dma_access.control_be));
if control.select() {
self.selector = control.select() as u16;
}
let len = u32::from_be(dma_access.length_be);
let addr = u64::from_be(dma_access.address_be);
let ret = if control.read() {
self.dma_read(self.selector, len, addr)
} else if control.write() {
Err(ErrorKind::InvalidInput.into())
} else if control.skip() {
self.data_offset += len;
Ok(())
} else {
Err(ErrorKind::InvalidData.into())
};
let mut access_resp = AccessControl(0);
if let Err(e) = ret {
error!("fw_cfg: dma operation {dma_access:x?}: {e:x?}");
access_resp.set_error(true);
}
if let Err(e) = self.memory.memory().write(
&access_resp.0.to_be_bytes(),
GuestAddress(dma_address + core::mem::offset_of!(FwCfgDmaAccess, control_be) as u64),
) {
error!("fw_cfg: finishing dma: {e:?}")
}
}
pub fn add_kernel_data(&mut self, file: &File) -> Result<()> {
let mut buffer = vec![0u8; size_of::<boot_params>()];
file.read_exact_at(&mut buffer, 0)?;
let bp = boot_params::from_mut_slice(&mut buffer).unwrap();
#[cfg(target_arch = "x86_64")]
{
// must set to 4 for backwards compatibility
// https://docs.kernel.org/arch/x86/boot.html#the-real-mode-kernel-header
if bp.hdr.setup_sects == 0 {
bp.hdr.setup_sects = 4;
}
// wildcard boot loader type
bp.hdr.type_of_loader = 0xff;
}
#[cfg(target_arch = "aarch64")]
let kernel_start = bp.text_offset;
#[cfg(target_arch = "x86_64")]
let kernel_start = (bp.hdr.setup_sects as usize + 1) * 512;
self.known_items[FW_CFG_SETUP_SIZE as usize] = FwCfgContent::U32(buffer.len() as u32);
self.known_items[FW_CFG_SETUP_DATA as usize] = FwCfgContent::Bytes(buffer);
self.known_items[FW_CFG_KERNEL_SIZE as usize] =
FwCfgContent::U32(file.metadata()?.len() as u32 - kernel_start as u32);
self.known_items[FW_CFG_KERNEL_DATA as usize] =
FwCfgContent::File(kernel_start as u64, file.try_clone()?);
Ok(())
}
pub fn add_kernel_cmdline(&mut self, s: std::ffi::CString) {
let bytes = s.into_bytes_with_nul();
self.known_items[FW_CFG_CMDLINE_SIZE as usize] = FwCfgContent::U32(bytes.len() as u32);
self.known_items[FW_CFG_CMDLINE_DATA as usize] = FwCfgContent::Bytes(bytes);
}
pub fn add_acpi(
&mut self,
rsdp: Rsdp,
tables: Vec<u8>,
table_checksums: Vec<(usize, usize)>,
table_pointers: Vec<usize>,
) -> Result<()> {
let acpi_table = AcpiTable {
rsdp,
tables,
table_checksums,
table_pointers,
};
let [table_loader, acpi_rsdp, apci_tables] = create_acpi_loader(acpi_table);
self.add_item(table_loader)?;
self.add_item(acpi_rsdp)?;
self.add_item(apci_tables)
}
pub fn add_initramfs_data(&mut self, file: &File) -> Result<()> {
let initramfs_size = file.metadata()?.len();
self.known_items[FW_CFG_INITRD_SIZE as usize] = FwCfgContent::U32(initramfs_size as _);
self.known_items[FW_CFG_INITRD_DATA as usize] = FwCfgContent::File(0, file.try_clone()?);
Ok(())
}
fn read_content(content: &FwCfgContent, offset: u32, data: &mut [u8], size: u32) -> Option<u8> {
let start = offset as usize;
let end = start + size as usize;
match content {
FwCfgContent::Bytes(b) => {
if b.len() >= size as usize {
data.copy_from_slice(&b[start..end]);
}
}
FwCfgContent::Slice(s) => {
if s.len() >= size as usize {
data.copy_from_slice(&s[start..end]);
}
}
FwCfgContent::File(o, f) => {
f.read_exact_at(data, o + offset as u64).ok()?;
}
FwCfgContent::U32(n) => {
let bytes = n.to_le_bytes();
data.copy_from_slice(&bytes[start..end]);
}
};
Some(size as u8)
}
fn read_data(&mut self, data: &mut [u8], size: u32) -> u8 {
let ret = if let Some(content) = self.known_items.get(self.selector as usize) {
Self::read_content(content, self.data_offset, data, size)
} else if let Some(item) = self.items.get((self.selector - FW_CFG_FILE_FIRST) as usize) {
Self::read_content(&item.content, self.data_offset, data, size)
} else {
error!("fw_cfg: selector {:#x} does not exist.", self.selector);
None
};
if let Some(val) = ret {
self.data_offset += size;
val
} else {
0
}
}
}
impl BusDevice for FwCfg {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let port = offset + PORT_FW_CFG_BASE;
let size = data.len();
match (port, size) {
(PORT_FW_CFG_SELECTOR, _) => {
error!("fw_cfg: selector register is write-only.");
}
(PORT_FW_CFG_DATA, _) => _ = self.read_data(data, size as u32),
(PORT_FW_CFG_DMA_HI, 4) => {
let addr = self.dma_address;
let addr_hi = (addr >> 32) as u32;
data.copy_from_slice(&addr_hi.to_be_bytes());
}
(PORT_FW_CFG_DMA_LO, 4) => {
let addr = self.dma_address;
let addr_lo = (addr & 0xffff_ffff) as u32;
data.copy_from_slice(&addr_lo.to_be_bytes());
}
_ => {
debug!(
"fw_cfg: read from unknown port {port:#x}: {size:#x} bytes and offset {offset:#x}."
);
}
};
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
let port = offset + PORT_FW_CFG_BASE;
let size = data.size();
match (port, size) {
(PORT_FW_CFG_SELECTOR, 2) => {
let mut buf = [0u8; 2];
buf[..size].copy_from_slice(&data[..size]);
#[cfg(target_arch = "x86_64")]
let val = u16::from_le_bytes(buf);
#[cfg(target_arch = "aarch64")]
let val = u16::from_be_bytes(buf);
self.selector = val;
self.data_offset = 0;
}
(PORT_FW_CFG_DATA, 1) => error!("fw_cfg: data register is read-only."),
(PORT_FW_CFG_DMA_HI, 4) => {
let mut buf = [0u8; 4];
buf[..size].copy_from_slice(&data[..size]);
let val = u32::from_be_bytes(buf);
self.dma_address &= 0xffff_ffff;
self.dma_address |= (val as u64) << 32;
}
(PORT_FW_CFG_DMA_LO, 4) => {
let mut buf = [0u8; 4];
buf[..size].copy_from_slice(&data[..size]);
let val = u32::from_be_bytes(buf);
self.dma_address &= !0xffff_ffff;
self.dma_address |= val as u64;
self.do_dma();
}
_ => debug!(
"fw_cfg: write to unknown port {port:#x}: {size:#x} bytes and offset {offset:#x} ."
),
};
None
}
}
#[cfg(test)]
mod tests {
use std::ffi::CString;
use std::io::Write;
use vmm_sys_util::tempfile::TempFile;
use super::*;
#[cfg(target_arch = "x86_64")]
const SELECTOR_OFFSET: u64 = 0;
#[cfg(target_arch = "aarch64")]
const SELECTOR_OFFSET: u64 = 8;
#[cfg(target_arch = "x86_64")]
const DATA_OFFSET: u64 = 1;
#[cfg(target_arch = "aarch64")]
const DATA_OFFSET: u64 = 0;
#[cfg(target_arch = "x86_64")]
const DMA_OFFSET: u64 = 4;
#[cfg(target_arch = "aarch64")]
const DMA_OFFSET: u64 = 16;
#[test]
fn test_signature() {
let gm = GuestMemoryAtomic::new(
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), RAM_64BIT_START.0 as usize)]).unwrap(),
);
let mut fw_cfg = FwCfg::new(gm);
let mut data = vec![0u8];
let mut sig_iter = FW_CFG_DMA_SIGNATURE.into_iter();
fw_cfg.write(0, SELECTOR_OFFSET, &[FW_CFG_SIGNATURE as u8, 0]);
loop {
if let Some(char) = sig_iter.next() {
fw_cfg.read(0, DATA_OFFSET, &mut data);
assert_eq!(data[0], char);
} else {
return;
}
}
}
#[test]
fn test_kernel_cmdline() {
let gm = GuestMemoryAtomic::new(
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), RAM_64BIT_START.0 as usize)]).unwrap(),
);
let mut fw_cfg = FwCfg::new(gm);
let cmdline = *b"cmdline\0";
fw_cfg.add_kernel_cmdline(CString::from_vec_with_nul(cmdline.to_vec()).unwrap());
let mut data = vec![0u8];
let mut cmdline_iter = cmdline.into_iter();
fw_cfg.write(0, SELECTOR_OFFSET, &[FW_CFG_CMDLINE_DATA as u8, 0]);
loop {
if let Some(char) = cmdline_iter.next() {
fw_cfg.read(0, DATA_OFFSET, &mut data);
assert_eq!(data[0], char);
} else {
return;
}
}
}
#[test]
fn test_initram_fs() {
let gm = GuestMemoryAtomic::new(
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), RAM_64BIT_START.0 as usize)]).unwrap(),
);
let mut fw_cfg = FwCfg::new(gm);
let temp = TempFile::new().unwrap();
let mut temp_file = temp.as_file();
let initram_content = b"this is the initramfs";
let written = temp_file.write(initram_content);
assert_eq!(written.unwrap(), 21);
let _ = fw_cfg.add_initramfs_data(temp_file);
let mut data = vec![0u8];
let mut initram_iter = (*initram_content).into_iter();
fw_cfg.write(0, SELECTOR_OFFSET, &[FW_CFG_INITRD_DATA as u8, 0]);
loop {
if let Some(char) = initram_iter.next() {
fw_cfg.read(0, DATA_OFFSET, &mut data);
assert_eq!(data[0], char);
} else {
return;
}
}
}
#[test]
fn test_dma() {
let code = [
0xba, 0xf8, 0x03, 0x00, 0xd8, 0x04, b'0', 0xee, 0xb0, b'\n', 0xee, 0xf4,
];
let content = FwCfgContent::Bytes(code.to_vec());
let mem_size = 0x1000;
let load_addr = GuestAddress(0x1000);
let mem: GuestMemoryMmap<AtomicBitmap> =
GuestMemoryMmap::from_ranges(&[(load_addr, mem_size)]).unwrap();
// Note: In firmware we would just allocate FwCfgDmaAccess struct
// and use address of struct (&) as dma address
let mut access_control = AccessControl(0);
// bit 1 = read access
access_control.set_read(true);
// length of data to access
let length_be = (code.len() as u32).to_be();
// guest address for data
let code_address = 0x1900_u64;
let address_be = code_address.to_be();
let mut access = FwCfgDmaAccess {
control_be: access_control.0.to_be(), // bit(1) = read bit
length_be,
address_be,
};
// access address is where to put the code
let access_address = GuestAddress(load_addr.0);
let address_bytes = access_address.0.to_be_bytes();
let dma_lo: [u8; 4] = address_bytes[0..4].try_into().unwrap();
let dma_hi: [u8; 4] = address_bytes[4..8].try_into().unwrap();
// writing the FwCfgDmaAccess to mem (this would just be self.dma_access.as_ref() in guest)
let _ = mem.write(access.as_mut_bytes(), access_address);
let mem_m = GuestMemoryAtomic::new(mem.clone());
let mut fw_cfg = FwCfg::new(mem_m);
let cfg_item = FwCfgItem {
name: "code".to_string(),
content,
};
let _ = fw_cfg.add_item(cfg_item);
let mut data = [0u8; 12];
let _ = mem.read(&mut data, GuestAddress(code_address));
assert_ne!(data, code);
fw_cfg.write(0, SELECTOR_OFFSET, &[FW_CFG_FILE_FIRST as u8, 0]);
fw_cfg.write(0, DMA_OFFSET, &dma_lo);
fw_cfg.write(0, DMA_OFFSET + 4, &dma_hi);
let _ = mem.read(&mut data, GuestAddress(code_address));
assert_eq!(data, code);
}
}

View File

@@ -12,8 +12,8 @@ use std::{io, result};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_device::interrupt::InterruptSourceGroup;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use crate::{read_le_u32, write_le_u32};
@@ -28,10 +28,10 @@ const GPIORIE: u64 = 0x414; // Raw Interrupt Status Register
const GPIOMIS: u64 = 0x418; // Masked Interrupt Status Register
const GPIOIC: u64 = 0x41c; // Interrupt Clear Register
const GPIOAFSEL: u64 = 0x420; // Mode Control Select Register
// From 0x424 to 0xFDC => reserved space.
// From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers.
// These registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral.
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
// From 0x424 to 0xFDC => reserved space.
// From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers.
// These registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral.
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
const GPIO_ID: [u8; 8] = [0x61, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// ID Margins
const GPIO_ID_LOW: u64 = 0xfe0;
@@ -43,11 +43,11 @@ const N_GPIOS: u32 = 8;
pub enum Error {
#[error("Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("GPIO interrupt disabled by guest driver.")]
#[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}.")]
#[error("Could not trigger GPIO interrupt")]
GpioInterruptFailure(#[source] io::Error),
#[error("Invalid GPIO Input key triggered: {0}")]
GpioTriggerKeyFailure(u32),
}

View File

@@ -45,7 +45,7 @@ impl BusDevice for I8042Device {
if data.len() == 1 && data[0] == 0xfe && offset == 3 {
info!("i8042 reset signalled");
if let Err(e) = self.reset_evt.write(1) {
error!("Error triggering i8042 reset event: {}", e);
error!("Error triggering i8042 reset event: {e}");
}
// Spin until we are sure the reset_evt has been handled and that when
// we return from the KVM_RUN we will exit rather than re-enter the guest.

View File

@@ -8,6 +8,8 @@
mod cmos;
#[cfg(target_arch = "x86_64")]
mod debug_port;
#[cfg(feature = "fw_cfg")]
pub mod fw_cfg;
#[cfg(target_arch = "x86_64")]
mod fwdebug;
#[cfg(target_arch = "aarch64")]
@@ -22,6 +24,8 @@ mod uart_pl011;
pub use self::cmos::Cmos;
#[cfg(target_arch = "x86_64")]
pub use self::debug_port::DebugPort;
#[cfg(feature = "fw_cfg")]
pub use self::fw_cfg::FwCfg;
#[cfg(target_arch = "x86_64")]
pub use self::fwdebug::FwDebugDevice;
#[cfg(target_arch = "aarch64")]

View File

@@ -4,16 +4,18 @@
//! ARM PL031 Real Time Clock
//!
//! This module implements a PL031 Real Time Clock (RTC) that provides to provides long time base counter.
//! This is achieved by generating an interrupt signal after counting for a programmed number of cycles of
//! a real-time clock input.
//! This module implements part of a PL031 Real Time Clock (RTC):
//! * provide a clock value via RTCDR
//! * no alarm is implemented through the match register
//! * no interrupt is generated
//! * RTC cannot be disabled via RTCCR
//! * no test registers
//!
use std::result;
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 crate::{read_le_u32, write_le_u32};
@@ -29,11 +31,11 @@ const RTCIMSC: u64 = 0x10; // Interrupt Mask Set or Clear Register.
const RTCRIS: u64 = 0x14; // Raw Interrupt Status.
const RTCMIS: u64 = 0x18; // Masked Interrupt Status.
const RTCICR: u64 = 0x1c; // Interrupt Clear Register.
// From 0x020 to 0xFDC => reserved space.
// From 0xFE0 to 0x1000 => Peripheral and PrimeCell Identification Registers which are Read Only registers.
// AMBA standard devices have CIDs (Cell IDs) and PIDs (Peripheral IDs). The linux kernel will look for these in order to assert the identity
// of these devices (i.e look at the `amba_device_try_add` function).
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
// From 0x020 to 0xFDC => reserved space.
// From 0xFE0 to 0x1000 => Peripheral and PrimeCell Identification Registers which are Read Only registers.
// AMBA standard devices have CIDs (Cell IDs) and PIDs (Peripheral IDs). The linux kernel will look for these in order to assert the identity
// of these devices (i.e look at the `amba_device_try_add` function).
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
const PL031_ID: [u8; 8] = [0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// We are only interested in the margins.
const AMBA_ID_LOW: u64 = 0xFE0;
@@ -45,8 +47,6 @@ pub const NANOS_PER_SECOND: u64 = 1_000_000_000;
pub enum Error {
#[error("Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("Failed to trigger interrupt: {0}")]
InterruptFailure(io::Error),
}
type Result<T> = result::Result<T, Error>;
@@ -107,31 +107,20 @@ pub struct Rtc {
match_value: u32,
// Writes to this register load an update value into the RTC.
load: u32,
imsc: u32,
ris: u32,
interrupt: Arc<dyn InterruptSourceGroup>,
}
impl Rtc {
/// Constructs an AMBA PL031 RTC device.
pub fn new(interrupt: Arc<dyn InterruptSourceGroup>) -> Self {
pub fn new() -> Self {
Self {
// This is used only for duration measuring purposes.
previous_now: Instant::now(),
tick_offset: get_time(ClockType::Real) as i64,
match_value: 0,
load: 0,
imsc: 0,
ris: 0,
interrupt,
}
}
fn trigger_interrupt(&mut self) -> Result<()> {
self.interrupt.trigger(0).map_err(Error::InterruptFailure)?;
Ok(())
}
fn get_time(&self) -> u32 {
let ts = (self.tick_offset as i128)
+ (Instant::now().duration_since(self.previous_now).as_nanos() as i128);
@@ -155,16 +144,8 @@ impl Rtc {
// we want to terminate the execution of the process.
self.tick_offset = seconds_to_nanoseconds(i64::from(val)).unwrap();
}
RTCIMSC => {
self.imsc = val & 1;
self.trigger_interrupt()?;
}
RTCICR => {
// As per above mentioned doc, the interrupt is cleared by writing any data value to
// the Interrupt Clear Register.
self.ris = 0;
self.trigger_interrupt()?;
}
RTCIMSC => (),
RTCICR => (),
RTCCR => (), // ignore attempts to turn off the timer.
o => {
return Err(Error::BadWriteOffset(o));
@@ -174,6 +155,12 @@ impl Rtc {
}
}
impl Default for Rtc {
fn default() -> Self {
Self::new()
}
}
impl BusDevice for Rtc {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let mut read_ok = true;
@@ -189,10 +176,10 @@ impl BusDevice for Rtc {
self.match_value
}
RTCLR => self.load,
RTCCR => 1, // RTC is always enabled.
RTCIMSC => self.imsc,
RTCRIS => self.ris,
RTCMIS => self.ris & self.imsc,
RTCCR => 1, // RTC is always enabled.
RTCIMSC => 0, // Interrupt is always disabled.
RTCRIS => 0,
RTCMIS => 0,
_ => {
read_ok = false;
0
@@ -230,9 +217,6 @@ impl BusDevice for Rtc {
#[cfg(test)]
mod tests {
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
use vmm_sys_util::eventfd::EventFd;
use super::*;
use crate::{
read_be_u16, read_be_u32, read_le_i32, read_le_u16, read_le_u64, write_be_u16,
@@ -366,45 +350,9 @@ mod tests {
assert!(seconds_to_nanoseconds(9_223_372_037).is_none());
}
struct TestInterrupt {
event_fd: EventFd,
}
impl InterruptSourceGroup for TestInterrupt {
fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
self.event_fd.write(1)
}
fn update(
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
_set_gsi: bool,
) -> result::Result<(), std::io::Error> {
Ok(())
}
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
Ok(())
}
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
Some(self.event_fd.try_clone().unwrap())
}
}
impl TestInterrupt {
fn new(event_fd: EventFd) -> Self {
TestInterrupt { event_fd }
}
}
#[test]
fn test_rtc_read_write_and_event() {
let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let mut rtc = Rtc::new(Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
let mut rtc = Rtc::new();
let mut data = [0; 4];
// Read and write to the MR register.
@@ -427,15 +375,13 @@ mod tests {
assert_eq!((v / NANOS_PER_SECOND) as u32, v_read);
// Read and write to IMSC register.
// Test with non zero value.
// Test with non zero value. Our device ignores the write.
let non_zero = 1;
write_le_u32(&mut data, non_zero);
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data);
// The interrupt line should be on.
assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() == 1);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
let v = read_le_u32(&data);
assert_eq!(non_zero & 1, v);
assert_eq!(0, v);
// Now test with 0.
write_le_u32(&mut data, 0);
@@ -447,8 +393,6 @@ mod tests {
// Read and write to the ICR register.
write_le_u32(&mut data, 1);
rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCICR, &data);
// The interrupt line should be on.
assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() > 1);
let v_before = read_le_u32(&data);
rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data);

View File

@@ -10,8 +10,8 @@ use std::sync::{Arc, Barrier};
use std::{io, result};
use serde::{Deserialize, Serialize};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_device::interrupt::InterruptSourceGroup;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::errno::Result;

View File

@@ -13,8 +13,8 @@ use std::{io, result};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_device::interrupt::InterruptSourceGroup;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use crate::{read_le_u32, write_le_u32};
@@ -51,14 +51,14 @@ const AMBA_ID_HIGH: u64 = 0x401;
pub enum Error {
#[error("pl011_write: Bad Write Offset: {0}")]
BadWriteOffset(u64),
#[error("pl011: DMA not implemented.")]
#[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),
#[error("Failed to trigger interrupt")]
InterruptFailure(#[source] io::Error),
#[error("Failed to write")]
WriteAllFailure(#[source] io::Error),
#[error("Failed to flush")]
FlushFailure(#[source] io::Error),
}
type Result<T> = result::Result<T, Error>;

View File

@@ -24,6 +24,8 @@ pub mod gic;
pub mod interrupt_controller;
#[cfg(target_arch = "x86_64")]
pub mod ioapic;
#[cfg(feature = "ivshmem")]
pub mod ivshmem;
pub mod legacy;
#[cfg(feature = "pvmemcontrol")]
pub mod pvmemcontrol;
@@ -33,7 +35,9 @@ pub mod pvpanic;
pub mod tpm;
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
pub use self::pvpanic::{PvPanicDevice, PVPANIC_DEVICE_MMIO_SIZE};
#[cfg(feature = "ivshmem")]
pub use self::ivshmem::IvshmemDevice;
pub use self::pvpanic::{PVPANIC_DEVICE_MMIO_SIZE, PvPanicDevice};
bitflags! {
pub struct AcpiNotificationFlags: u8 {

View File

@@ -36,7 +36,7 @@ const MINOR_VERSION: u64 = 0;
#[derive(Error, Debug)]
pub enum Error {
// device errors
#[error("Guest gave us bad memory addresses: {0}")]
#[error("Guest gave us bad memory addresses")]
GuestMemory(#[source] GuestMemoryError),
#[error("Guest sent us invalid request")]
InvalidRequest,
@@ -51,7 +51,7 @@ pub enum Error {
InvalidArgument(u64),
#[error("Unknown function code: {0}")]
UnknownFunctionCode(u64),
#[error("Libc call fail: {0}")]
#[error("Libc call fail")]
LibcFail(#[source] std::io::Error),
}
@@ -137,7 +137,8 @@ impl PvmemcontrolTransport {
}
unsafe fn as_register(self) -> PvmemcontrolTransportRegister {
self.payload.register
// SAFETY: We access initialized data.
unsafe { self.payload.register }
}
}
@@ -484,7 +485,7 @@ impl PvmemcontrolBusDevice {
}
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 = (name != 0).then(|| CString::new(format!("pvmemcontrol-{name}")).unwrap());
let name_ptr = if let Some(name) = &name {
name.as_ptr()
} else {
@@ -519,7 +520,7 @@ impl PvmemcontrolBusDevice {
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),
@@ -698,10 +699,12 @@ impl PciDevice for PvmemcontrolPciDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> Option<Arc<Barrier>> {
self.configuration
.write_config_register(reg_idx, offset, data);
None
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
(
self.configuration
.write_config_register(reg_idx, offset, data),
None,
)
}
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
@@ -716,14 +719,6 @@ impl PciDevice for PvmemcontrolPciDevice {
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>>,

View File

@@ -9,9 +9,9 @@ use std::sync::{Arc, Barrier, Mutex};
use anyhow::anyhow;
use pci::{
BarReprogrammingParams, PciBarConfiguration, PciBarPrefetchable, PciBarRegionType,
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
PCI_CONFIGURATION_ID,
BarReprogrammingParams, PCI_CONFIGURATION_ID, PciBarConfiguration, PciBarPrefetchable,
PciBarRegionType, PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType,
PciSubclass,
};
use serde::{Deserialize, Serialize};
use thiserror::Error;
@@ -31,9 +31,9 @@ const PVPANIC_CRASH_LOADED: u8 = 1 << 1;
#[derive(Debug, Error)]
pub enum PvPanicError {
#[error("Failed creating PvPanicDevice: {0}")]
#[error("Failed creating PvPanicDevice")]
CreatePvPanicDevice(#[source] anyhow::Error),
#[error("Failed to retrieve PciConfigurationState: {0}")]
#[error("Failed to retrieve PciConfigurationState")]
RetrievePciConfigurationState(#[source] anyhow::Error),
}
@@ -68,8 +68,7 @@ impl PvPanicDevice {
let pci_configuration_state =
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
PvPanicError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
"Failed to get PciConfigurationState from Snapshot: {e}"
))
})?;
@@ -88,7 +87,11 @@ impl PvPanicDevice {
);
let command: [u8; 2] = [0x03, 0x01];
configuration.write_config_register(1, 0, &command);
let bar_reprogram = configuration.write_config_register(1, 0, &command);
assert!(
bar_reprogram.is_empty(),
"No bar reprogrammig is expected from writing to the COMMAND register"
);
let state: Option<PvPanicDeviceState> = snapshot
.as_ref()
@@ -96,8 +99,7 @@ impl PvPanicDevice {
.transpose()
.map_err(|e| {
PvPanicError::CreatePvPanicDevice(anyhow!(
"Failed to get PvPanicDeviceState from Snapshot: {}",
e
"Failed to get PvPanicDeviceState from Snapshot: {e}"
))
})?;
let events = if let Some(state) = state {
@@ -144,7 +146,7 @@ impl BusDevice for PvPanicDevice {
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
let event = self.event_to_string(data[0]);
info!("pvpanic got guest event {}", event);
info!("pvpanic got guest event {event}");
event!("guest", "panic", "event", &event);
None
}
@@ -156,24 +158,18 @@ impl PciDevice for PvPanicDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> Option<Arc<Barrier>> {
self.configuration
.write_config_register(reg_idx, offset, data);
None
) -> (Vec<BarReprogrammingParams>, 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_reg(reg_idx)
}
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>>,

View File

@@ -12,15 +12,15 @@ use arch::aarch64::layout::{TPM_SIZE, TPM_START};
#[cfg(target_arch = "x86_64")]
use arch::x86_64::layout::{TPM_SIZE, TPM_START};
use thiserror::Error;
use tpm::emulator::{BackendCmd, Emulator};
use tpm::TPM_CRB_BUFFER_MAX;
use tpm::emulator::{BackendCmd, Emulator};
use vm_device::BusDevice;
#[derive(Error, Debug)]
pub enum Error {
#[error("Emulator doesn't implement min required capabilities: {0}")]
#[error("Emulator doesn't implement min required capabilities")]
CheckCaps(#[source] anyhow::Error),
#[error("Failed to initialize tpm: {0}")]
#[error("Failed to initialize tpm")]
Init(#[source] anyhow::Error),
}
type Result<T> = anyhow::Result<T, Error>;
@@ -221,7 +221,7 @@ pub struct Tpm {
impl Tpm {
pub fn new(path: String) -> Result<Self> {
let emulator = Emulator::new(path)
.map_err(|e| Error::Init(anyhow!("Failed while initializing tpm Emulator: {:?}", e)))?;
.map_err(|e| Error::Init(anyhow!("Failed while initializing tpm Emulator: {e:?}")))?;
let mut tpm = Tpm {
emulator,
regs: [0; TPM_CRB_R_MAX],
@@ -331,8 +331,7 @@ impl Tpm {
if let Err(e) = self.emulator.startup_tpm(self.backend_buff_size) {
return Err(Error::Init(anyhow!(
"Failed while running Startup TPM. Error: {:?}",
e
"Failed while running Startup TPM. Error: {e:?}"
)));
}
Ok(())
@@ -458,10 +457,9 @@ impl BusDevice for Tpm {
CRB_CTRL_CANCEL => {
if v == CRB_CANCEL_INVOKE
&& (self.regs[CRB_CTRL_START as usize] & CRB_START_INVOKE != 0)
&& let Err(e) = self.emulator.cancel_cmd()
{
if let Err(e) = self.emulator.cancel_cmd() {
error!("Failed to run cancel command. Error: {:?}", e);
}
error!("Failed to run cancel command. Error: {e:?}");
}
}
CRB_CTRL_START => {
@@ -482,10 +480,7 @@ impl BusDevice for Tpm {
}
}
CRB_LOC_CTRL => {
warn!(
"CRB_LOC_CTRL locality to write = {:?} val = {:?}",
locality, v
);
warn!("CRB_LOC_CTRL locality to write = {locality:?} val = {v:?}");
match v {
CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT => {}
CRB_LOC_CTRL_RELINQUISH => {
@@ -518,7 +513,7 @@ impl BusDevice for Tpm {
);
}
_ => {
error!("Invalid value to write in CRB_LOC_CTRL {:#X} ", v);
error!("Invalid value to write in CRB_LOC_CTRL {v:#X} ");
}
}
}

View File

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

View File

@@ -56,13 +56,6 @@ or a fd with `--api-socket fd=...`.
```
$ ./target/debug/cloud-hypervisor --api-socket path=/tmp/cloud-hypervisor.sock
Cloud Hypervisor Guest
API server: /tmp/cloud-hypervisor.sock
vCPUs: 1
Memory: 512 MB
Kernel: None
Kernel cmdline:
Disk(s): None
```
#### REST API Endpoints
@@ -121,13 +114,6 @@ the REST API available at `/tmp/cloud-hypervisor.sock`:
```
$ ./target/debug/cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock
Cloud Hypervisor Guest
API server: /tmp/cloud-hypervisor.sock
vCPUs: 1
Memory: 512 MB
Kernel: None
Kernel cmdline:
Disk(s): None
```
##### Create a Virtual Machine

View File

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

77
docs/fw_cfg.md Normal file
View File

@@ -0,0 +1,77 @@
# Firmware Configuration (fw_cfg) Device
The `fw_cfg` device is a QEMU-compatible device that allows the hypervisor to pass configuration and data to the guest operating system. This is particularly useful for firmware to access information like ACPI tables, kernel images, initramfs, kernel command lines, and other arbitrary data blobs.
Cloud Hypervisor implements the `fw_cfg` device with DMA-enabled access.
## Purpose
The `fw_cfg` device serves as a generic information channel between the VMM and the guest. It can be used to:
* Load the kernel, initramfs, and kernel command line for direct kernel boot with firmware.
* Provide ACPI tables to the guest firmware or OS.
* Pass custom configuration files or data blobs (e.g., attestation data, SEV-SNP launch secrets) to the guest.
* Supply an E820 memory map to the guest.
## Enabling `fw_cfg`
The `fw_cfg` device is enabled via the `fw_cfg` feature flag when building Cloud Hypervisor:
```bash
cargo build --features fw_cfg
```
## Guest Kernel Configuration
For the guest Linux kernel to recognize and use the `fw_cfg` device via sysfs, the following kernel configuration option must be enabled:
* `CONFIG_FW_CFG_SYSFS=y`
This option allows the kernel to expose `fw_cfg` entries under `/sys/firmware/qemu_fw_cfg/by_name/`.
## Command Line Options
The `fw_cfg` device is configured using the `--fw-cfg-config` command-line option.
**Parameters:**
* `e820=on|off`: (Default: `on`) Whether to add an E820 memory map entry to `fw_cfg`.
* `kernel=on|off`: (Default: `on`) Whether to add the kernel image (specified by `--kernel`) to `fw_cfg`.
* `cmdline=on|off`: (Default: `on`) Whether to add the kernel command line (specified by `--cmdline`) to `fw_cfg`.
* `initramfs=on|off`: (Default: `on`) Whether to add the initramfs image (specified by `--initramfs`) to `fw_cfg`.
* `acpi_table=on|off`: (Default: `on`) Whether to add generated ACPI tables to `fw_cfg`.
* `items=[... : ...]`: A list of custom key-value pairs to be exposed via `fw_cfg`.
* `name=<guest_sysfs_path>`: The path under which the item will appear in the guest's sysfs (e.g., `opt/org.example/my-data`).
* `file=<host_file_path>`: The path to the file on the host whose content will be provided to the guest for this item.
**Example Usage:**
1. **Direct kernel boot with custom `fw_cfg` entries:**
```bash
cloud-hypervisor \
--kernel /path/to/vmlinux \
--cmdline "console=hvc0 root=/dev/vda1" \
--disk path=/path/to/rootfs.img \
--fw-cfg-config initramfs=off,items=[name=opt/org.mycorp/setup_info,file=/tmp/guest_setup.txt] \
...
```
In the guest, `/tmp/guest_setup.txt` from the host will be accessible at `/sys/firmware/qemu_fw_cfg/by_name/opt/org.mycorp/setup_info/raw`.
2. **Disabling `fw_cfg` explicitly:**
```bash
cloud-hypervisor \
--fw-cfg-config disable \
...
```
## Accessing `fw_cfg` Items in the Guest
If `CONFIG_FW_CFG_SYSFS` is enabled in the guest kernel, items added to `fw_cfg` can be accessed via sysfs.
For example, an item added with `name=opt/org.example/my-data` will be available at:
`/sys/firmware/qemu_fw_cfg/by_name/opt/org.example/my-data/raw`
The `raw` file contains the binary content of the host file provided.
Standard items like kernel, initramfs, cmdline, and ACPI tables also have predefined names (e.g., `etc/kernel`, `etc/cmdline`) if they are enabled to be passed via `fw_cfg`.

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