Compare commits

...

61 Commits

Author SHA1 Message Date
Praveen K Paladugu 3599daf378 vmm: cleanup legacy console device management
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 22:40:43 +00:00
Praveen K Paladugu 2ba4bec97f vmm: refactor DeviceManager to use console_info
While adding console devices, DeviceManager will now use the FDs in
console_info instead of creating them.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 22:27:28 +00:00
Praveen K Paladugu 118870b122 vmm: populate console_info during vm actions
Use pre_create_console_devices method to create and populate console
device FDs into console_info element in Vmm Object.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 22:24:58 +00:00
Praveen K Paladugu 1585a06aca vmm: save console_resize_pipe info to Vmm
With this change all the information to manage console devices is no
available in Vmm Object.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 19:53:35 +00:00
Praveen K Paladugu 32d2fb5023 vmm: move listen_for_sigwinch_on_tty method
Move listen_for_sigwinch_on_tty to sigwinch_listener.rs module.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 19:53:35 +00:00
Praveen K Paladugu 310a30bbcb vmm: Introduce console_devices module
Introduce ConsoleInfo struct. This struct will be used to store info
about console devices that are pre-created and passed during vm_boot.

Move set_raw_mode method to console_device to consolidate console
management methods into a single module.

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

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>

vmm: pre create console devices

pre create console devices during vm_create and capture the related FDs
in console_info.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2024-05-08 19:49:48 +00:00
Rob Bradford 7e25cc2aa0 build: Add "fuzzing" as a valid cfg(..) attribute
The compiler is now able to warn if an invalid attribute (e.g like a
feature) is not available.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Fixes: #6134

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Only use c_uchar in those types, and drop char_array.

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

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

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

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

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

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

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

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

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

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

Fixes: #6421

Signed-off-by: Songqian Li <sionli@tencent.com>
2024-04-29 11:13:05 +00:00
Rob Bradford 4f96fa15a8 build: Release v39.0
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-27 12:21:30 +00:00
dependabot[bot] ed1f906d46 build: Bump serde_with from 3.7.0 to 3.8.0 in /fuzz
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.7.0...v3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-27 08:27:15 +00:00
Thomas Barrett 3b64b7723b docs: add documentation for GPUDirect P2P
Signed-off-by: Thomas Barrett <tbarrett1200@icloud.com>
2024-04-27 07:47:40 +00:00
dependabot[bot] 6925750622 build: Bump cc from 1.0.92 to 1.0.95
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.92 to 1.0.95.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.92...1.0.95)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-26 23:35:31 +00:00
dependabot[bot] 26808bfb71 build: Bump serde from 1.0.197 to 1.0.198 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.198.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.198)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 23:49:29 +00:00
Rob Bradford b89657ea22 hypervisor, vmm: Don't re-export the contents of mshv_bindings::*
The contents of this crate may change and cause conflicts - re-exporting
the contents is unnecessary.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-25 20:53:53 +00:00
Rob Bradford 1ef2b488c7 build: Bump kvm-bindings and crates that depend on it
This removes the custom fork as the upstream version now has serde
support.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-25 20:53:53 +00:00
Rob Bradford 7be69edf51 hypervisor: kvm: Introduce Mutex around VcpuFd
This is required as the VcpuFd::run and VcpuFd::set_immediate_exit
methods now take a &mut self. I explored alternative solutions:

1. Using RefCell for runtime interior mutability - the Vcpu trait is
   Sync and it's not possible to use RefCell with types that are Sync.
2. Using UnsafeCell - the mutable reference nature of ::run and and
   ::set_kvm_immediate_exit was added for a reason so it unwise to
   bypass this.
3. Adjusting the trait interface to expose the &mut self - this requires
   an Arc<Mutex<>> around the hypervisor::vcpu::Vcpu object and was very
   intrusive.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-25 20:53:53 +00:00
Rob Bradford c022063ae8 hypervisor: Remove unused VmExit enum members
The members for {Io, Mmio}{Read, Write} are unused as instead exits of
those types are handled through the VmOps interface. Removing these is
also a prerequisite due to changes in the mutability of the
VcpuFd::run() method.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-25 20:53:53 +00:00
dependabot[bot] e6aa57e3b9 build: Bump signal-hook-registry from 1.4.1 to 1.4.2 in /fuzz
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.1 to 1.4.2.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.1...registry-v1.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 00:32:55 +00:00
Muminul Islam 512591ba1c hypervisor: rework VP state components
On Microsoft Hypervisor, we need to save/restore five
VP state components which are as follows:
    1. Local APIC
    2. Xsave
    3. Synthetic Message Page
    4. Synthetic Event Flags Page
    5. Synthetic Timers

In the MSHV crate we created a single struct for all the
components and API to get/set the states.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-04-24 16:02:54 +00:00
Thomas Barrett e7e856d8ac vmm: add pci_segment mmio aperture configs
When using multiple PCI segments, the 32-bit and 64-bit mmio
aperture is split equally between each segment. Add an option
to configure the 'weight'. For example, a PCI segment with a
`mmio32_aperture_weight` of 2 will be allocated twice as much
32-bit mmio space as a normal PCI segment.

Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
2024-04-24 09:35:19 +00:00
dependabot[bot] a84bc06874 build: Bump proc-macro2 from 1.0.79 to 1.0.81 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.79 to 1.0.81.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.79...1.0.81)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 00:07:58 +00:00
Muminul Islam a750e6ec15 vmm: Add filter entry for MSHV_GET_PARTITION_PROPERTY
Add seccomp rule for getting partition property on MSHV.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-04-23 08:31:10 +00:00
dependabot[bot] 82d275ccaa build: Bump windows_x86_64_gnullvm from 0.52.4 to 0.52.5 in /fuzz
Bumps [windows_x86_64_gnullvm](https://github.com/microsoft/windows-rs) from 0.52.4 to 0.52.5.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-23 00:08:22 +00:00
Rob Bradford 10ab87d6a3 misc: Migrate away from versionize
Replace with serde instead.

Fixes: #6370

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2024-04-22 17:10:55 +00:00
98 changed files with 1680 additions and 1316 deletions

View File

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

View File

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

View File

@ -88,6 +88,7 @@ jobs:
if: github.event_name == 'create' && github.event.ref_type == 'tag'
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
./${{ matrix.platform.name_ch }}
./${{ matrix.platform.name_ch_remote }}

129
Cargo.lock generated
View File

@ -115,8 +115,6 @@ dependencies = [
"serde",
"thiserror",
"uuid",
"versionize",
"versionize_derive",
"vm-fdt",
"vm-memory",
"vm-migration",
@ -249,9 +247,9 @@ dependencies = [
[[package]]
name = "async-recursion"
version = "1.1.0"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5"
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
@ -278,9 +276,9 @@ dependencies = [
[[package]]
name = "async-task"
version = "4.7.0"
version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
@ -320,15 +318,6 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitfield-struct"
version = "0.5.6"
@ -362,11 +351,10 @@ dependencies = [
"libc",
"log",
"remain",
"serde",
"smallvec",
"thiserror",
"uuid",
"versionize",
"versionize_derive",
"virtio-bindings",
"virtio-queue",
"vm-memory",
@ -413,9 +401,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.92"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
[[package]]
name = "cfg-if"
@ -453,7 +441,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "cloud-hypervisor"
version = "38.0.0"
version = "39.0.0"
dependencies = [
"anyhow",
"api_client",
@ -490,9 +478,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "concurrent-queue"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
@ -524,12 +512,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crc64"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
@ -612,10 +594,9 @@ dependencies = [
"libc",
"log",
"pci",
"serde",
"thiserror",
"tpm",
"versionize",
"versionize_derive",
"vm-allocator",
"vm-device",
"vm-memory",
@ -1090,8 +1071,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "igvm"
version = "0.1.9"
source = "git+https://github.com/microsoft/igvm?branch=main#494aac2318df4111a2737d360ea46f74f5350223"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac310e8c44854718e087821efe5d30ed18f3f864b3926b777ef70aadbb9834d"
dependencies = [
"bitfield-struct",
"crc32fast",
@ -1106,8 +1088,9 @@ dependencies = [
[[package]]
name = "igvm_defs"
version = "0.1.9"
source = "git+https://github.com/microsoft/igvm?branch=main#494aac2318df4111a2737d360ea46f74f5350223"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a57e85ae9109a6281a1fc279456f830237a94a65873a331ad858814b1a09b2b"
dependencies = [
"bitfield-struct",
"open-enum",
@ -1181,19 +1164,20 @@ dependencies = [
[[package]]
name = "kvm-bindings"
version = "0.7.0"
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.7.0#2dcf85d4f8aa55befcaa996b699ddb18ec9ed059"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82e7e8725a39a0015e511a46cc1f7d90cecc180db1610c4d0d4339a9e48bd21"
dependencies = [
"serde",
"serde_derive",
"vmm-sys-util",
"zerocopy",
]
[[package]]
name = "kvm-ioctls"
version = "0.16.0"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c"
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
dependencies = [
"bitflags 2.5.0",
"kvm-bindings",
@ -1343,7 +1327,7 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07"
[[package]]
name = "mshv-bindings"
version = "0.1.1"
source = "git+https://github.com/rust-vmm/mshv?branch=main#ef8fd01cf48b2e72bd6405a613a6ef65b43729d7"
source = "git+https://github.com/rust-vmm/mshv?branch=main#76bbc508a4152d020dd42061d4505c64e320ba94"
dependencies = [
"libc",
"num_enum",
@ -1356,7 +1340,7 @@ dependencies = [
[[package]]
name = "mshv-ioctls"
version = "0.1.1"
source = "git+https://github.com/rust-vmm/mshv?branch=main#ef8fd01cf48b2e72bd6405a613a6ef65b43729d7"
source = "git+https://github.com/rust-vmm/mshv?branch=main#76bbc508a4152d020dd42061d4505c64e320ba94"
dependencies = [
"libc",
"mshv-bindings",
@ -1396,8 +1380,6 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"virtio-bindings",
"virtio-queue",
"vm-memory",
@ -1600,8 +1582,6 @@ dependencies = [
"log",
"serde",
"thiserror",
"versionize",
"versionize_derive",
"vfio-bindings",
"vfio-ioctls",
"vfio_user",
@ -2210,18 +2190,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.58"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
dependencies = [
"proc-macro2",
"quote",
@ -2356,37 +2336,10 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "versionize"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
dependencies = [
"bincode",
"crc64",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn 1.0.109",
"versionize_derive",
"vmm-sys-util",
]
[[package]]
name = "versionize_derive"
version = "0.1.6"
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "vfio-bindings"
version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#4e937a514d9025f953eeb837fb8dafe035d9a8fd"
source = "git+https://github.com/rust-vmm/vfio?branch=main#df7de6b256a1ece422804119938f6a325b2ce99b"
dependencies = [
"vmm-sys-util",
]
@ -2394,7 +2347,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#4e937a514d9025f953eeb837fb8dafe035d9a8fd"
source = "git+https://github.com/rust-vmm/vfio?branch=main#df7de6b256a1ece422804119938f6a325b2ce99b"
dependencies = [
"byteorder",
"kvm-bindings",
@ -2428,9 +2381,9 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
checksum = "6be08d1166d41a78861ad50212ab3f9eca0729c349ac3a7a8f557c62406b87cc"
dependencies = [
"bitflags 2.5.0",
"libc",
@ -2440,9 +2393,9 @@ dependencies = [
[[package]]
name = "vhost-user-backend"
version = "0.13.1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c8c447d076ac508d78cb45664d203df7989e891656dce260a7e93d72352c9a"
checksum = "1f0ffb1dd8e00a708a0e2c32d5efec5812953819888591fff9ff68236b8a5096"
dependencies = [
"libc",
"log",
@ -2515,10 +2468,9 @@ dependencies = [
"seccompiler",
"serde",
"serde_json",
"serde_with",
"serial_buffer",
"thiserror",
"versionize",
"versionize_derive",
"vhost",
"virtio-bindings",
"virtio-queue",
@ -2532,9 +2484,9 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d"
checksum = "07d8406e7250c934462de585d8f2d2781c31819bca1fbb7c5e964ca6bbaabfe8"
dependencies = [
"log",
"virtio-bindings",
@ -2589,8 +2541,6 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"vm-memory",
]
@ -2617,6 +2567,7 @@ dependencies = [
"cfg-if",
"clap",
"devices",
"dhat",
"epoll",
"event_monitor",
"flume",
@ -2646,8 +2597,6 @@ dependencies = [
"thiserror",
"tracer",
"uuid",
"versionize",
"versionize_derive",
"vfio-ioctls",
"vfio_user",
"virtio-devices",

View File

@ -1,6 +1,6 @@
[package]
name = "cloud-hypervisor"
version = "38.0.0"
version = "39.0.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
default-run = "cloud-hypervisor"
@ -15,7 +15,7 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
# a.) A dependency requires it,
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
# c.) There is a security issue that is addressed by the toolchain update.
rust-version = "1.74.1"
rust-version = "1.77.0"
[profile.release]
lto = true
@ -42,7 +42,7 @@ option_parser = { path = "option_parser" }
seccompiler = "0.4.0"
serde_json = "1.0.115"
signal-hook = "0.3.17"
thiserror = "1.0.58"
thiserror = "1.0.60"
tpm = { path = "tpm"}
tracer = { path = "tracer" }
vmm = { path = "vmm" }
@ -50,11 +50,6 @@ vmm-sys-util = "0.12.1"
vm-memory = "0.14.1"
zbus = { version = "3.15.2", optional = true }
# List of patched crates
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
[dev-dependencies]
dirs = "5.0.1"
net_util = { path = "net_util" }
@ -68,7 +63,7 @@ wait-timeout = "0.2.0"
[features]
default = ["kvm", "io_uring"]
dbus_api = ["zbus", "vmm/dbus_api"]
dhat-heap = ["dhat"] # For heap profiling
dhat-heap = ["dhat", "vmm/dhat-heap"] # For heap profiling
guest_debug = ["vmm/guest_debug"]
igvm = ["vmm/igvm", "mshv"]
io_uring = ["vmm/io_uring"]

View File

@ -17,10 +17,8 @@ libc = "0.2.153"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.21"
serde = { version = "1.0.197", features = ["rc", "derive"] }
thiserror = "1.0.58"
thiserror = "1.0.60"
uuid = "1.8.0"
versionize = "0.2.0"
versionize_derive = "0.1.6"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }

View File

@ -18,9 +18,6 @@ use std::fmt;
use std::result;
use std::sync::Arc;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
use versionize_derive::Versionize;
use vm_migration::VersionMapped;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
@ -58,7 +55,7 @@ pub enum Error {
pub type Result<T> = result::Result<T, Error>;
/// Type for memory region types.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum RegionType {
/// RAM type
Ram,
@ -76,8 +73,6 @@ pub enum RegionType {
Reserved,
}
impl VersionMapped for RegionType {}
/// Module for aarch64 related functionality.
#[cfg(target_arch = "aarch64")]
pub mod aarch64;

View File

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

View File

@ -8,7 +8,7 @@
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::{get_x2apic_id, mpspec};
use crate::GuestMemoryMmap;
use libc::c_char;
use libc::c_uchar;
use std::mem;
use std::result;
use std::slice;
@ -82,18 +82,13 @@ pub type Result<T> = result::Result<T, Error>;
// a large number for FC usecases.
pub const MAX_SUPPORTED_CPUS: u32 = 254;
// Convenience macro for making arrays of diverse character types.
macro_rules! char_array {
($t:ty; $( $c:expr ),*) => ( [ $( $c as $t ),* ] )
}
// Most of these variables are sourced from the Intel MP Spec 1.4.
const SMP_MAGIC_IDENT: [c_char; 4] = char_array!(c_char; '_', 'M', 'P', '_');
const MPC_SIGNATURE: [c_char; 4] = char_array!(c_char; 'P', 'C', 'M', 'P');
const MPC_SPEC: i8 = 4;
const MPC_OEM: [c_char; 8] = char_array!(c_char; 'F', 'C', ' ', ' ', ' ', ' ', ' ', ' ');
const MPC_PRODUCT_ID: [c_char; 12] = ['0' as c_char; 12];
const BUS_TYPE_ISA: [u8; 6] = char_array!(u8; 'I', 'S', 'A', ' ', ' ', ' ');
const SMP_MAGIC_IDENT: &[c_uchar; 4] = b"_MP_";
const MPC_SIGNATURE: &[c_uchar; 4] = b"PCMP";
const MPC_SPEC: u8 = 4;
const MPC_OEM: &[c_uchar; 8] = b"FC ";
const MPC_PRODUCT_ID: &[c_uchar; 12] = &[b'0'; 12];
const BUS_TYPE_ISA: &[c_uchar; 6] = b"ISA ";
const APIC_VERSION: u8 = 0x14;
const CPU_STEPPING: u32 = 0x600;
const CPU_FEATURE_APIC: u32 = 0x200;
@ -168,7 +163,7 @@ pub fn setup_mptable(
{
let mut mpf_intel = MpfIntelWrapper(mpspec::mpf_intel::default());
let size = mem::size_of::<MpfIntelWrapper>() as u64;
mpf_intel.0.signature = SMP_MAGIC_IDENT;
mpf_intel.0.signature = *SMP_MAGIC_IDENT;
mpf_intel.0.length = 1;
mpf_intel.0.specification = 4;
mpf_intel.0.physptr = (base_mp.raw_value() + size) as u32;
@ -209,7 +204,7 @@ pub fn setup_mptable(
let mut mpc_bus = MpcBusWrapper(mpspec::mpc_bus::default());
mpc_bus.0.type_ = mpspec::MP_BUS as u8;
mpc_bus.0.busid = 0;
mpc_bus.0.bustype = BUS_TYPE_ISA;
mpc_bus.0.bustype = *BUS_TYPE_ISA;
mem.write_obj(mpc_bus, base_mp)
.map_err(Error::WriteMpcBus)?;
base_mp = base_mp.unchecked_add(size as u64);
@ -280,14 +275,14 @@ pub fn setup_mptable(
{
let mut mpc_table = MpcTableWrapper(mpspec::mpc_table::default());
mpc_table.0.signature = MPC_SIGNATURE;
mpc_table.0.signature = *MPC_SIGNATURE;
mpc_table.0.length = table_end.unchecked_offset_from(table_base) as u16;
mpc_table.0.spec = MPC_SPEC;
mpc_table.0.oem = MPC_OEM;
mpc_table.0.productid = MPC_PRODUCT_ID;
mpc_table.0.oem = *MPC_OEM;
mpc_table.0.productid = *MPC_PRODUCT_ID;
mpc_table.0.lapic = APIC_START.0 as u32;
checksum = checksum.wrapping_add(compute_checksum(&mpc_table.0));
mpc_table.0.checksum = (!checksum).wrapping_add(1) as i8;
mpc_table.0.checksum = (!checksum).wrapping_add(1);
mem.write_obj(mpc_table, table_base)
.map_err(Error::WriteMpcTable)?;
}

View File

@ -15,13 +15,12 @@ io-uring = { version = "0.6.3", optional = true }
libc = "0.2.153"
log = "0.4.21"
remain = "0.2.13"
serde = { version = "1.0.197", features = ["derive"] }
smallvec = "1.13.2"
thiserror = "1.0.58"
thiserror = "1.0.60"
uuid = { version = "1.8.0", features = ["v4"] }
versionize = "0.2.0"
versionize_derive = "0.1.6"
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1"

View File

@ -37,6 +37,7 @@ use crate::vhdx::{Vhdx, VhdxError};
#[cfg(feature = "io_uring")]
use io_uring::{opcode, IoUring, Probe};
use libc::{ioctl, S_IFBLK, S_IFMT};
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use std::alloc::{alloc_zeroed, dealloc, Layout};
use std::cmp;
@ -52,21 +53,17 @@ use std::sync::Arc;
use std::sync::MutexGuard;
use std::time::Instant;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::virtio_blk::*;
use virtio_queue::DescriptorChain;
use vm_memory::{
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
GuestMemoryError, GuestMemoryLoadGuard,
bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError,
GuestMemoryLoadGuard,
};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
const SECTOR_SHIFT: u8 = 9;
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
@ -196,8 +193,8 @@ pub enum RequestType {
Unsupported(u32),
}
pub fn request_type(
mem: &GuestMemoryMmap,
pub fn request_type<B: Bitmap + 'static>(
mem: &vm_memory::GuestMemoryMmap<B>,
desc_addr: GuestAddress,
) -> result::Result<RequestType, Error> {
let type_ = mem.read_obj(desc_addr).map_err(Error::GuestMemory)?;
@ -210,7 +207,10 @@ pub fn request_type(
}
}
fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64, Error> {
fn sector<B: Bitmap + 'static>(
mem: &vm_memory::GuestMemoryMmap<B>,
desc_addr: GuestAddress,
) -> result::Result<u64, Error> {
const SECTOR_OFFSET: usize = 8;
let addr = match mem.checked_offset(desc_addr, SECTOR_OFFSET) {
Some(v) => v,
@ -240,8 +240,8 @@ pub struct Request {
}
impl Request {
pub fn parse(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap>>,
pub fn parse<B: Bitmap + 'static>(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
access_platform: Option<&Arc<dyn AccessPlatform>>,
) -> result::Result<Request, Error> {
let hdr_desc = desc_chain
@ -332,11 +332,11 @@ impl Request {
Ok(req)
}
pub fn execute<T: Seek + Read + Write>(
pub fn execute<T: Seek + Read + Write, B: Bitmap + 'static>(
&self,
disk: &mut T,
disk_nsectors: u64,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
serial: &[u8],
) -> result::Result<u32, ExecuteError> {
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
@ -389,9 +389,9 @@ impl Request {
Ok(len)
}
pub fn execute_async(
pub fn execute_async<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
disk_nsectors: u64,
disk_image: &mut dyn AsyncIo,
serial: &[u8],
@ -544,7 +544,7 @@ impl Request {
}
}
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
#[repr(C, packed)]
pub struct VirtioBlockConfig {
pub capacity: u64,
@ -567,7 +567,7 @@ pub struct VirtioBlockConfig {
pub write_zeroes_may_unmap: u8,
pub unused1: [u8; 3],
}
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
#[repr(C, packed)]
pub struct VirtioBlockGeometry {
pub cylinders: u16,
@ -659,7 +659,9 @@ where
let mut slices: SmallVec<[IoSliceMut; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSliceMut wraps around libc::iovec
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
slices.push(IoSliceMut::new(unsafe {
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
}));
}
let result = {
@ -692,7 +694,9 @@ where
let mut slices: SmallVec<[IoSlice; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSlice wraps around libc::iovec
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
slices.push(IoSlice::new(unsafe {
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
}));
}
let result = {

View File

@ -1631,7 +1631,7 @@ impl PunchHole for QcowFile {
let mut remaining = length;
let mut offset = offset;
while remaining > 0 {
let chunk_length = min(remaining, std::usize::MAX as u64) as usize;
let chunk_length = min(remaining, usize::MAX as u64) as usize;
self.deallocate_bytes(offset, chunk_length)?;
remaining -= chunk_length as u64;
offset += chunk_length as u64;

View File

@ -15,10 +15,9 @@ hypervisor = { path = "../hypervisor" }
libc = "0.2.153"
log = "0.4.21"
pci = { path = "../pci" }
thiserror = "1.0.58"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.60"
tpm = { path = "../tpm" }
versionize = "0.2.0"
versionize_derive = "0.1.6"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = "0.14.1"

View File

@ -11,19 +11,16 @@
use super::interrupt_controller::{Error, InterruptController};
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use std::result;
use std::sync::{Arc, Barrier};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
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, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
type Result<T> = result::Result<T, Error>;
@ -136,7 +133,7 @@ pub struct Ioapic {
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct IoapicState {
id_reg: u32,
reg_sel: u32,
@ -144,7 +141,6 @@ pub struct IoapicState {
used_entries: [bool; NUM_IOAPIC_PINS],
apic_address: u64,
}
impl VersionMapped for IoapicState {}
impl BusDevice for Ioapic {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
@ -444,7 +440,7 @@ impl Snapshottable for Ioapic {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -8,16 +8,13 @@
//!
use crate::{read_le_u32, write_le_u32};
use serde::{Deserialize, Serialize};
use std::result;
use std::sync::{Arc, Barrier};
use std::{fmt, io};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
const OFS_DATA: u64 = 0x400; // Data Register
const GPIODIR: u64 = 0x400; // Direction Register
@ -89,7 +86,7 @@ pub struct Gpio {
interrupt: Arc<dyn InterruptSourceGroup>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct GpioState {
data: u32,
old_in_data: u32,
@ -102,8 +99,6 @@ pub struct GpioState {
afsel: u32,
}
impl VersionMapped for GpioState {}
impl Gpio {
/// Constructs an PL061 GPIO device.
pub fn new(
@ -328,7 +323,7 @@ impl Snapshottable for Gpio {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -153,24 +153,6 @@ impl fmt::Display for LocalTime {
}
}
/// Holds a micro-second resolution timestamp with both the real time and cpu time.
#[derive(Clone)]
pub struct TimestampUs {
/// Real time in microseconds.
pub time_us: u64,
/// Cpu time in microseconds.
pub cputime_us: u64,
}
impl Default for TimestampUs {
fn default() -> TimestampUs {
TimestampUs {
time_us: get_time(ClockType::Monotonic) / 1000,
cputime_us: get_time(ClockType::ProcessCpu) / 1000,
}
}
}
/// Returns a timestamp in nanoseconds based on the provided clock type.
///
/// # Arguments

View File

@ -5,16 +5,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::sync::{Arc, Barrier};
use std::{io, result};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::errno::Result;
const LOOP_SIZE: usize = 0x40;
@ -74,7 +71,7 @@ pub struct Serial {
out: Option<Box<dyn io::Write + Send>>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct SerialState {
interrupt_enable: u8,
interrupt_identification: u8,
@ -86,7 +83,6 @@ pub struct SerialState {
baud_divisor: u16,
in_buffer: Vec<u8>,
}
impl VersionMapped for SerialState {}
impl Serial {
pub fn new(
@ -334,7 +330,7 @@ impl Snapshottable for Serial {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -7,18 +7,15 @@
//!
use crate::{read_le_u32, write_le_u32};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use std::{io, result};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
/* Registers */
const UARTDR: u64 = 0;
@ -94,7 +91,7 @@ pub struct Pl011 {
timestamp: std::time::Instant,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct Pl011State {
flags: u32,
lcr: u32,
@ -113,8 +110,6 @@ pub struct Pl011State {
read_trigger: u32,
}
impl VersionMapped for Pl011State {}
impl Pl011 {
/// Constructs an AMBA PL011 UART device.
pub fn new(
@ -454,7 +449,7 @@ impl Snapshottable for Pl011 {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -9,18 +9,15 @@ use pci::{
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
PCI_CONFIGURATION_ID,
};
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::result;
use std::sync::{Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::{BusDevice, Resource};
use vm_memory::{Address, GuestAddress};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
const PVPANIC_VENDOR_ID: u16 = 0x1b36;
const PVPANIC_DEVICE_ID: u16 = 0x0011;
@ -60,23 +57,20 @@ pub struct PvPanicDevice {
bar_regions: Vec<PciBarConfiguration>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct PvPanicDeviceState {
events: u8,
}
impl VersionMapped for PvPanicDeviceState {}
impl PvPanicDevice {
pub fn new(id: String, snapshot: Option<Snapshot>) -> Result<Self, PvPanicError> {
let pci_configuration_state =
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
.map_err(|e| {
PvPanicError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
))
})?;
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
PvPanicError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
))
})?;
let mut configuration = PciConfiguration::new(
PVPANIC_VENDOR_ID,
@ -97,7 +91,7 @@ impl PvPanicDevice {
let state: Option<PvPanicDeviceState> = snapshot
.as_ref()
.map(|s| s.to_versioned_state())
.map(|s| s.to_state())
.transpose()
.map_err(|e| {
PvPanicError::CreatePvPanicDevice(anyhow!(
@ -259,7 +253,7 @@ impl Snapshottable for PvPanicDevice {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let mut snapshot = Snapshot::new_from_versioned_state(&self.state())?;
let mut snapshot = Snapshot::new_from_state(&self.state())?;
// Snapshot PciConfiguration
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);

View File

@ -122,4 +122,64 @@ $ ls /sys/kernel/iommu_groups/22/devices/
This means these two devices are under the same IOMMU group 22. In such case,
it is important to bind both devices to VFIO and pass them both through the
VM, otherwise this could cause some functional and security issues.
VM, otherwise this could cause some functional and security issues.
### Advanced Configuration Options
When using NVIDIA GPUs in a VFIO passthrough configuration, advanced
configuration options are supported to enable GPUDirect P2P DMA over
PCIe. When enabled, loads and stores between GPUs use native PCIe
peer-to-peer transactions instead of a shared memory buffer. This drastically
decreases P2P latency between GPUs. This functionality is supported by
cloud-hypervisor on NVIDIA Turing, Ampere, Hopper, and Lovelace GPUs.
The NVIDIA driver does not enable GPUDirect P2P over PCIe within guests
by default because hardware support for routing P2P TLP between PCIe root
ports is optional. PCIe P2P should always be supported between devices
on the same PCIe switch. The `x_nv_gpudirect_clique` config argument may
be used to signal support for PCIe P2P traffic between NVIDIA VFIO endpoints.
The guest driver assumes that P2P traffic is supported between all endpoints
that are part of the same clique.
```
--device path=/sys/bus/pci/devices/0000:01:00.0/,x_nv_gpudirect_clique=0
```
The following command can be run on the guest to verify that GPUDirect P2P is
correctly enabled.
```
nvidia-smi topo -p2p r
GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7
GPU0 X OK OK OK OK OK OK OK
GPU1 OK X OK OK OK OK OK OK
GPU2 OK OK X OK OK OK OK OK
GPU3 OK OK OK X OK OK OK OK
GPU4 OK OK OK OK X OK OK OK
GPU5 OK OK OK OK OK X OK OK
GPU6 OK OK OK OK OK OK X OK
GPU7 OK OK OK OK OK OK OK X
```
Some VFIO devices have a 32-bit mmio BAR. When using many such devices, it is
possible to exhaust the 32-bit mmio space available on a PCI segment. The
following example demonstrates an example device with a 16 MiB 32-bit mmio BAR.
```
lspci -s 0000:01:00.0 -v
0000:01:00.0 3D controller: NVIDIA Corporation Device 26b9 (rev a1)
[...]
Memory at f9000000 (32-bit, non-prefetchable) [size=16M]
Memory at 46000000000 (64-bit, prefetchable) [size=64G]
Memory at 48040000000 (64-bit, prefetchable) [size=32M]
[...]
```
When using multiple PCI segments, the 32-bit mmio address space available to
be allocated to VFIO devices is equally split between all PCI segments by
default. This can be tuned with the `--pci-segment` flag. The following example
demonstrates a guest with two PCI segments. 2/3 of the 32-bit mmio address
space is available for use by devices on PCI segment 0 and 1/3 of the 32-bit
mmio address space is available for use by devices on PCI segment 1.
```
--platform num_pci_segments=2
--pci-segment pci_segment=0,mmio32_aperture_weight=2
--pci-segment pci_segment=1,mmio32_aperture_weight=1
```

182
fuzz/Cargo.lock generated
View File

@ -50,9 +50,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys",
@ -97,8 +97,6 @@ dependencies = [
"serde",
"thiserror",
"uuid",
"versionize",
"versionize_derive",
"vm-fdt",
"vm-memory",
"vm-migration",
@ -107,18 +105,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bitflags"
@ -142,11 +131,10 @@ dependencies = [
"libc",
"log",
"remain",
"serde",
"smallvec",
"thiserror",
"uuid",
"versionize",
"versionize_derive",
"virtio-bindings",
"virtio-queue",
"vm-memory",
@ -211,7 +199,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "cloud-hypervisor"
version = "38.0.0"
version = "39.0.0"
dependencies = [
"anyhow",
"api_client",
@ -273,12 +261,6 @@ dependencies = [
"debug-helper",
]
[[package]]
name = "crc64"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
[[package]]
name = "darling"
version = "0.20.8"
@ -300,7 +282,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.58",
"syn",
]
[[package]]
@ -311,7 +293,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core",
"quote",
"syn 2.0.58",
"syn",
]
[[package]]
@ -334,10 +316,9 @@ dependencies = [
"libc",
"log",
"pci",
"serde",
"thiserror",
"tpm",
"versionize",
"versionize_derive",
"vm-allocator",
"vm-device",
"vm-memory",
@ -457,9 +438,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jobserver"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
@ -475,19 +456,20 @@ dependencies = [
[[package]]
name = "kvm-bindings"
version = "0.7.0"
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.7.0#2dcf85d4f8aa55befcaa996b699ddb18ec9ed059"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82e7e8725a39a0015e511a46cc1f7d90cecc180db1610c4d0d4339a9e48bd21"
dependencies = [
"serde",
"serde_derive",
"vmm-sys-util",
"zerocopy",
]
[[package]]
name = "kvm-ioctls"
version = "0.16.0"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c"
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
dependencies = [
"bitflags 2.5.0",
"kvm-bindings",
@ -497,9 +479,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]]
name = "libfuzzer-sys"
@ -574,8 +556,6 @@ dependencies = [
"rate_limiter",
"serde",
"thiserror",
"versionize",
"versionize_derive",
"virtio-bindings",
"virtio-queue",
"vm-memory",
@ -604,8 +584,6 @@ dependencies = [
"log",
"serde",
"thiserror",
"versionize",
"versionize_derive",
"vfio-bindings",
"vfio-ioctls",
"vfio_user",
@ -618,9 +596,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.79"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
@ -653,7 +631,7 @@ checksum = "ad9f2390298a947ee0aa6073d440e221c0726188cfbcdf9604addb6ee393eb4a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
]
[[package]]
@ -679,22 +657,22 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.197"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
]
[[package]]
@ -710,9 +688,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.7.0"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
dependencies = [
"serde",
"serde_derive",
@ -721,14 +699,14 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.7.0"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
]
[[package]]
@ -747,9 +725,9 @@ dependencies = [
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
@ -783,20 +761,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "1.0.109"
version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
@ -820,7 +787,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
]
[[package]]
@ -868,37 +835,10 @@ dependencies = [
"getrandom",
]
[[package]]
name = "versionize"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
dependencies = [
"bincode",
"crc64",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn 1.0.109",
"versionize_derive",
"vmm-sys-util",
]
[[package]]
name = "versionize_derive"
version = "0.1.6"
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "vfio-bindings"
version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
dependencies = [
"vmm-sys-util",
]
@ -906,7 +846,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
dependencies = [
"byteorder",
"kvm-bindings",
@ -938,9 +878,9 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
checksum = "6be08d1166d41a78861ad50212ab3f9eca0729c349ac3a7a8f557c62406b87cc"
dependencies = [
"bitflags 2.5.0",
"libc",
@ -973,10 +913,9 @@ dependencies = [
"seccompiler",
"serde",
"serde_json",
"serde_with",
"serial_buffer",
"thiserror",
"versionize",
"versionize_derive",
"vhost",
"virtio-bindings",
"virtio-queue",
@ -990,9 +929,9 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d"
checksum = "07d8406e7250c934462de585d8f2d2781c31819bca1fbb7c5e964ca6bbaabfe8"
dependencies = [
"log",
"virtio-bindings",
@ -1047,8 +986,6 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"vm-memory",
]
@ -1095,8 +1032,6 @@ dependencies = [
"thiserror",
"tracer",
"uuid",
"versionize",
"versionize_derive",
"vfio-ioctls",
"vfio_user",
"virtio-devices",
@ -1149,7 +1084,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
"wasm-bindgen-shared",
]
@ -1171,7 +1106,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -1215,13 +1150,14 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
@ -1230,15 +1166,15 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
@ -1246,6 +1182,12 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
@ -1260,9 +1202,9 @@ checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
@ -1288,5 +1230,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
"syn",
]

View File

@ -15,7 +15,7 @@ igvm = []
block = { path = "../block" }
devices = { path = "../devices" }
epoll = "4.3.3"
libc = "0.2.153"
libc = "0.2.154"
libfuzzer-sys = "0.4.7"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
@ -23,8 +23,8 @@ net_util = { path = "../net_util" }
once_cell = "1.19.0"
seccompiler = "0.4.0"
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.11.0"
vmm = { path = "../vmm" }
virtio-queue = "0.12.0"
vmm = { path = "../vmm", features = ["guest_debug"]}
vmm-sys-util = "0.12.1"
vm-memory = "0.14.1"
vm-migration = { path = "../vm-migration" }
@ -34,10 +34,6 @@ vm-virtio = { path = "../vm-virtio" }
[dependencies.cloud-hypervisor]
path = ".."
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
# Prevent this from interfering with workspaces
[workspace]
members = ["."]

View File

@ -105,7 +105,7 @@ impl RequestHandler for StubApiRequestHandler {
Ok(())
}
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
#[cfg(target_arch = "x86_64")]
fn vm_coredump(&mut self, _: &str) -> Result<(), VmError> {
Ok(())
}
@ -185,8 +185,8 @@ impl RequestHandler for StubApiRequestHandler {
sgx_epc: None,
numa: None,
watchdog: false,
#[cfg(feature = "guest_debug")]
gdb: false,
pci_segments: None,
platform: None,
tpm: None,
preserved_fds: None,

View File

@ -8,18 +8,18 @@ license = "Apache-2.0 OR BSD-3-Clause"
[features]
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"]
sev_snp = ["igvm_parser", "igvm_defs"]
sev_snp = ["igvm", "igvm_defs"]
tdx = []
[dependencies]
anyhow = "1.0.81"
byteorder = "1.5.0"
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
igvm = { version = "0.2.0", optional = true }
igvm_defs = { version = "0.2.0", optional = true }
libc = "0.2.153"
log = "0.4.21"
kvm-ioctls = { version = "0.16.0", optional = true }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0", features = ["with-serde", "fam-wrappers"], optional = true }
kvm-bindings = { version = "0.8.1", optional = true, features = ["serde"] }
kvm-ioctls = { version = "0.17.0", optional = true }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
serde = { version = "1.0.197", features = ["rc", "derive"] }
@ -27,7 +27,7 @@ serde_with = { version = "3.7.0", default-features = false, features = ["macros"
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
thiserror = "1.0.58"
thiserror = "1.0.60"
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
optional = true

View File

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

View File

@ -107,14 +107,28 @@ pub enum HypervisorCpuError {
///
/// Setting Saved Processor Extended States error
///
#[cfg(feature = "kvm")]
#[error("Failed to set Saved Processor Extended States: {0}")]
SetXsaveState(#[source] anyhow::Error),
///
/// Getting Saved Processor Extended States error
///
#[cfg(feature = "kvm")]
#[error("Failed to get Saved Processor Extended States: {0}")]
GetXsaveState(#[source] anyhow::Error),
///
/// Getting the VP state components error
///
#[cfg(feature = "mshv")]
#[error("Failed to get VP State Components: {0}")]
GetAllVpStateComponents(#[source] anyhow::Error),
///
/// Setting the VP state components error
///
#[cfg(feature = "mshv")]
#[error("Failed to set VP State Components: {0}")]
SetAllVpStateComponents(#[source] anyhow::Error),
///
/// Setting Extended Control Registers error
///
#[error("Failed to set Extended Control Registers: {0}")]
@ -286,15 +300,9 @@ pub enum HypervisorCpuError {
}
#[derive(Debug)]
pub enum VmExit<'a> {
#[cfg(target_arch = "x86_64")]
IoOut(u16 /* port */, &'a [u8] /* data */),
#[cfg(target_arch = "x86_64")]
IoIn(u16 /* port */, &'a mut [u8] /* data */),
pub enum VmExit {
#[cfg(target_arch = "x86_64")]
IoapicEoi(u8 /* vector */),
MmioRead(u64 /* address */, &'a mut [u8]),
MmioWrite(u64 /* address */, &'a [u8]),
Ignore,
Reset,
Shutdown,

View File

@ -36,7 +36,6 @@ use std::os::unix::io::RawFd;
use std::result;
#[cfg(target_arch = "x86_64")]
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(target_arch = "aarch64")]
use std::sync::Mutex;
use std::sync::{Arc, RwLock};
use vmm_sys_util::eventfd::EventFd;
@ -455,12 +454,12 @@ impl vm::Vm for KvmVm {
id: u8,
vm_ops: Option<Arc<dyn VmOps>>,
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
let vc = self
let fd = self
.fd
.create_vcpu(id as u64)
.map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?;
let vcpu = KvmVcpu {
fd: vc,
fd: Arc::new(Mutex::new(fd)),
#[cfg(target_arch = "x86_64")]
msrs: self.msrs.clone(),
vm_ops,
@ -1170,7 +1169,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
/// Vcpu struct for KVM
pub struct KvmVcpu {
fd: VcpuFd,
fd: Arc<Mutex<VcpuFd>>,
#[cfg(target_arch = "x86_64")]
msrs: Vec<MsrEntry>,
vm_ops: Option<Arc<dyn vm::VmOps>>,
@ -1198,6 +1197,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
Ok(self
.fd
.lock()
.unwrap()
.get_regs()
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
.into())
@ -1219,6 +1220,8 @@ impl cpu::Vcpu for KvmVcpu {
for i in 0..31 {
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.regs.regs[i] = u64::from_le_bytes(bytes);
@ -1230,6 +1233,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, sp);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.regs.sp = u64::from_le_bytes(bytes);
@ -1238,6 +1243,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, pc);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.regs.pc = u64::from_le_bytes(bytes);
@ -1246,6 +1253,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, pstate);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.regs.pstate = u64::from_le_bytes(bytes);
@ -1254,6 +1263,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, sp_el1);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.sp_el1 = u64::from_le_bytes(bytes);
@ -1263,6 +1274,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, elr_el1);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.elr_el1 = u64::from_le_bytes(bytes);
@ -1272,6 +1285,8 @@ impl cpu::Vcpu for KvmVcpu {
for i in 0..KVM_NR_SPSR as usize {
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.spsr[i] = u64::from_le_bytes(bytes);
@ -1284,6 +1299,8 @@ impl cpu::Vcpu for KvmVcpu {
for i in 0..32 {
let mut bytes = [0_u8; 16];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.fp_regs.vregs[i] = u128::from_le_bytes(bytes);
@ -1294,6 +1311,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
let mut bytes = [0_u8; 4];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.fp_regs.fpsr = u32::from_le_bytes(bytes);
@ -1302,6 +1321,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
let mut bytes = [0_u8; 4];
self.fd
.lock()
.unwrap()
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.fp_regs.fpcr = u32::from_le_bytes(bytes);
@ -1315,6 +1336,8 @@ impl cpu::Vcpu for KvmVcpu {
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
let regs = (*regs).into();
self.fd
.lock()
.unwrap()
.set_regs(&regs)
.map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into()))
}
@ -1331,6 +1354,8 @@ impl cpu::Vcpu for KvmVcpu {
let mut off = offset_of!(user_pt_regs, regs);
for i in 0..31 {
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.regs[i].to_le_bytes(),
@ -1341,6 +1366,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, sp);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.sp.to_le_bytes(),
@ -1349,6 +1376,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, pc);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.pc.to_le_bytes(),
@ -1357,6 +1386,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(user_pt_regs, pstate);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.pstate.to_le_bytes(),
@ -1365,6 +1396,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, sp_el1);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.sp_el1.to_le_bytes(),
@ -1373,6 +1406,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, elr_el1);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.elr_el1.to_le_bytes(),
@ -1382,6 +1417,8 @@ impl cpu::Vcpu for KvmVcpu {
let mut off = offset_of!(kvm_regs, spsr);
for i in 0..KVM_NR_SPSR as usize {
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.spsr[i].to_le_bytes(),
@ -1393,6 +1430,8 @@ impl cpu::Vcpu for KvmVcpu {
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
for i in 0..32 {
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U128, off),
&state.fp_regs.vregs[i].to_le_bytes(),
@ -1403,6 +1442,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
&state.fp_regs.fpsr.to_le_bytes(),
@ -1411,6 +1452,8 @@ impl cpu::Vcpu for KvmVcpu {
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
&state.fp_regs.fpcr.to_le_bytes(),
@ -1426,6 +1469,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_sregs(&self) -> cpu::Result<SpecialRegisters> {
Ok(self
.fd
.lock()
.unwrap()
.get_sregs()
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
.into())
@ -1438,6 +1483,8 @@ impl cpu::Vcpu for KvmVcpu {
fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> {
let sregs = (*sregs).into();
self.fd
.lock()
.unwrap()
.set_sregs(&sregs)
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
}
@ -1449,6 +1496,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_fpu(&self) -> cpu::Result<FpuState> {
Ok(self
.fd
.lock()
.unwrap()
.get_fpu()
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
.into())
@ -1461,6 +1510,8 @@ impl cpu::Vcpu for KvmVcpu {
fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> {
let fpu: kvm_bindings::kvm_fpu = (*fpu).clone().into();
self.fd
.lock()
.unwrap()
.set_fpu(&fpu)
.map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into()))
}
@ -1476,6 +1527,8 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
self.fd
.lock()
.unwrap()
.set_cpuid2(&kvm_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
}
@ -1494,6 +1547,8 @@ impl cpu::Vcpu for KvmVcpu {
..Default::default()
};
self.fd
.lock()
.unwrap()
.enable_cap(&cap)
.map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into()))
}
@ -1505,6 +1560,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_cpuid2(&self, num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> {
let kvm_cpuid = self
.fd
.lock()
.unwrap()
.get_cpuid2(num_entries)
.map_err(|e| cpu::HypervisorCpuError::GetCpuid(e.into()))?;
@ -1520,6 +1577,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_lapic(&self) -> cpu::Result<LapicState> {
Ok(self
.fd
.lock()
.unwrap()
.get_lapic()
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
.into())
@ -1532,6 +1591,8 @@ impl cpu::Vcpu for KvmVcpu {
fn set_lapic(&self, klapic: &LapicState) -> cpu::Result<()> {
let klapic: kvm_bindings::kvm_lapic_state = (*klapic).clone().into();
self.fd
.lock()
.unwrap()
.set_lapic(&klapic)
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
}
@ -1545,6 +1606,8 @@ impl cpu::Vcpu for KvmVcpu {
let mut kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
let succ = self
.fd
.lock()
.unwrap()
.get_msrs(&mut kvm_msrs)
.map_err(|e| cpu::HypervisorCpuError::GetMsrEntries(e.into()))?;
@ -1567,6 +1630,8 @@ impl cpu::Vcpu for KvmVcpu {
let kvm_msrs: Vec<kvm_msr_entry> = msrs.iter().map(|e| (*e).into()).collect();
let kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
self.fd
.lock()
.unwrap()
.set_msrs(&kvm_msrs)
.map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into()))
}
@ -1577,6 +1642,8 @@ impl cpu::Vcpu for KvmVcpu {
fn get_mp_state(&self) -> cpu::Result<MpState> {
Ok(self
.fd
.lock()
.unwrap()
.get_mp_state()
.map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))?
.into())
@ -1587,6 +1654,8 @@ impl cpu::Vcpu for KvmVcpu {
///
fn set_mp_state(&self, mp_state: MpState) -> cpu::Result<()> {
self.fd
.lock()
.unwrap()
.set_mp_state(mp_state.into())
.map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into()))
}
@ -1598,6 +1667,8 @@ impl cpu::Vcpu for KvmVcpu {
fn translate_gva(&self, gva: u64, _flags: u64) -> cpu::Result<(u64, u32)> {
let tr = self
.fd
.lock()
.unwrap()
.translate_gva(gva)
.map_err(|e| cpu::HypervisorCpuError::TranslateVirtualAddress(e.into()))?;
// tr.valid is set if the GVA is mapped to valid GPA.
@ -1614,7 +1685,7 @@ impl cpu::Vcpu for KvmVcpu {
/// Triggers the running of the current virtual CPU returning an exit reason.
///
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
match self.fd.run() {
match self.fd.lock().unwrap().run() {
Ok(run) => match run {
#[cfg(target_arch = "x86_64")]
VcpuExit::IoIn(addr, data) => {
@ -1625,7 +1696,7 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
}
Ok(cpu::VmExit::IoIn(addr, data))
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
VcpuExit::IoOut(addr, data) => {
@ -1636,7 +1707,7 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
}
Ok(cpu::VmExit::IoOut(addr, data))
Ok(cpu::VmExit::Ignore)
}
#[cfg(target_arch = "x86_64")]
VcpuExit::IoapicEoi(vector) => Ok(cpu::VmExit::IoapicEoi(vector)),
@ -1669,7 +1740,7 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
}
Ok(cpu::VmExit::MmioRead(addr, data))
Ok(cpu::VmExit::Ignore)
}
VcpuExit::MmioWrite(addr, data) => {
if let Some(vm_ops) = &self.vm_ops {
@ -1679,7 +1750,7 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
}
Ok(cpu::VmExit::MmioWrite(addr, data))
Ok(cpu::VmExit::Ignore)
}
VcpuExit::Hyperv => Ok(cpu::VmExit::Hyperv),
#[cfg(feature = "tdx")]
@ -1708,7 +1779,7 @@ impl cpu::Vcpu for KvmVcpu {
/// potential soft lockups when being resumed.
///
fn notify_guest_clock_paused(&self) -> cpu::Result<()> {
if let Err(e) = self.fd.kvmclock_ctrl() {
if let Err(e) = self.fd.lock().unwrap().kvmclock_ctrl() {
// Linux kernel returns -EINVAL if the PV clock isn't yet initialised
// which could be because we're still in firmware or the guest doesn't
// use KVM clock.
@ -1770,6 +1841,8 @@ impl cpu::Vcpu for KvmVcpu {
}
}
self.fd
.lock()
.unwrap()
.set_guest_debug(&dbg)
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))
}
@ -1777,6 +1850,8 @@ impl cpu::Vcpu for KvmVcpu {
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
self.fd
.lock()
.unwrap()
.vcpu_init(kvi)
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
}
@ -1788,6 +1863,8 @@ impl cpu::Vcpu for KvmVcpu {
#[cfg(target_arch = "aarch64")]
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
self.fd
.lock()
.unwrap()
.get_reg_list(reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
}
@ -1820,6 +1897,8 @@ impl cpu::Vcpu for KvmVcpu {
| KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64);
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(id, &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
Ok(u64::from_le_bytes(bytes))
@ -1847,6 +1926,8 @@ impl cpu::Vcpu for KvmVcpu {
// Get the register index of the PSTATE (Processor State) register.
let pstate = offset_of!(user_pt_regs, pstate) + kreg_off;
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
&PSTATE_FAULT_BITS_64.to_le_bytes(),
@ -1858,6 +1939,8 @@ impl cpu::Vcpu for KvmVcpu {
// Setting the PC (Processor Counter) to the current program address (kernel address).
let pc = offset_of!(user_pt_regs, pc) + kreg_off;
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, pc),
&boot_ip.to_le_bytes(),
@ -1870,6 +1953,8 @@ impl cpu::Vcpu for KvmVcpu {
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
let regs0 = offset_of!(user_pt_regs, regs) + kreg_off;
self.fd
.lock()
.unwrap()
.set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
&fdt_start.to_le_bytes(),
@ -2021,6 +2106,8 @@ impl cpu::Vcpu for KvmVcpu {
let mut sys_regs: Vec<Register> = Vec::new();
let mut reg_list = RegList::new(500).unwrap();
self.fd
.lock()
.unwrap()
.get_reg_list(&mut reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
@ -2039,6 +2126,8 @@ impl cpu::Vcpu for KvmVcpu {
for index in indices.iter() {
let mut bytes = [0_u8; 8];
self.fd
.lock()
.unwrap()
.get_one_reg(*index, &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
sys_regs.push(kvm_bindings::kvm_one_reg {
@ -2153,6 +2242,8 @@ impl cpu::Vcpu for KvmVcpu {
// Set system registers
for reg in &state.sys_regs {
self.fd
.lock()
.unwrap()
.set_one_reg(reg.id, &reg.addr.to_le_bytes())
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
}
@ -2167,15 +2258,20 @@ impl cpu::Vcpu for KvmVcpu {
///
#[cfg(feature = "tdx")]
fn tdx_init(&self, hob_address: u64) -> cpu::Result<()> {
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
.map_err(cpu::HypervisorCpuError::InitializeTdx)
tdx_command(
&self.fd.lock().unwrap().as_raw_fd(),
TdxCommand::InitVcpu,
0,
hob_address,
)
.map_err(cpu::HypervisorCpuError::InitializeTdx)
}
///
/// Set the "immediate_exit" state
///
fn set_immediate_exit(&self, exit: bool) {
self.fd.set_kvm_immediate_exit(exit.into());
self.fd.lock().unwrap().set_kvm_immediate_exit(exit.into());
}
///
@ -2183,7 +2279,8 @@ impl cpu::Vcpu for KvmVcpu {
///
#[cfg(feature = "tdx")]
fn get_tdx_exit_details(&mut self) -> cpu::Result<TdxExitDetails> {
let kvm_run = self.fd.get_kvm_run();
let mut fd = self.fd.as_ref().lock().unwrap();
let kvm_run = fd.get_kvm_run();
// SAFETY: accessing a union field in a valid structure
let tdx_vmcall = unsafe {
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
@ -2212,7 +2309,8 @@ impl cpu::Vcpu for KvmVcpu {
///
#[cfg(feature = "tdx")]
fn set_tdx_status(&mut self, status: TdxExitStatus) {
let kvm_run = self.fd.get_kvm_run();
let mut fd = self.fd.as_ref().lock().unwrap();
let kvm_run = fd.get_kvm_run();
// SAFETY: accessing a union field in a valid structure
let tdx_vmcall = unsafe {
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
@ -2261,7 +2359,7 @@ impl cpu::Vcpu for KvmVcpu {
addr: 0x0,
flags: 0,
};
self.fd.has_device_attr(&cpu_attr).is_ok()
self.fd.lock().unwrap().has_device_attr(&cpu_attr).is_ok()
}
#[cfg(target_arch = "aarch64")]
@ -2279,9 +2377,13 @@ impl cpu::Vcpu for KvmVcpu {
flags: 0,
};
self.fd
.lock()
.unwrap()
.set_device_attr(&cpu_attr_irq)
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)?;
self.fd
.lock()
.unwrap()
.set_device_attr(&cpu_attr)
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)
}
@ -2291,7 +2393,7 @@ impl cpu::Vcpu for KvmVcpu {
/// Get the frequency of the TSC if available
///
fn tsc_khz(&self) -> cpu::Result<Option<u32>> {
match self.fd.get_tsc_khz() {
match self.fd.lock().unwrap().get_tsc_khz() {
Err(e) => {
if e.errno() == libc::EIO {
Ok(None)
@ -2308,7 +2410,7 @@ impl cpu::Vcpu for KvmVcpu {
/// Set the frequency of the TSC if available
///
fn set_tsc_khz(&self, freq: u32) -> cpu::Result<()> {
match self.fd.set_tsc_khz(freq) {
match self.fd.lock().unwrap().set_tsc_khz(freq) {
Err(e) => {
if e.errno() == libc::EIO {
Ok(())
@ -2325,7 +2427,7 @@ impl cpu::Vcpu for KvmVcpu {
/// Trigger NMI interrupt
///
fn nmi(&self) -> cpu::Result<()> {
match self.fd.nmi() {
match self.fd.lock().unwrap().nmi() {
Err(e) => {
if e.errno() == libc::EIO {
Ok(())
@ -2346,6 +2448,8 @@ impl KvmVcpu {
fn get_xsave(&self) -> cpu::Result<XsaveState> {
Ok(self
.fd
.lock()
.unwrap()
.get_xsave()
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))?
.into())
@ -2358,6 +2462,8 @@ impl KvmVcpu {
fn set_xsave(&self, xsave: &XsaveState) -> cpu::Result<()> {
let xsave: kvm_bindings::kvm_xsave = (*xsave).clone().into();
self.fd
.lock()
.unwrap()
.set_xsave(&xsave)
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
}
@ -2368,6 +2474,8 @@ impl KvmVcpu {
///
fn get_xcrs(&self) -> cpu::Result<ExtendedControlRegisters> {
self.fd
.lock()
.unwrap()
.get_xcrs()
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
}
@ -2378,6 +2486,8 @@ impl KvmVcpu {
///
fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> cpu::Result<()> {
self.fd
.lock()
.unwrap()
.set_xcrs(xcrs)
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
}
@ -2389,6 +2499,8 @@ impl KvmVcpu {
///
fn get_vcpu_events(&self) -> cpu::Result<VcpuEvents> {
self.fd
.lock()
.unwrap()
.get_vcpu_events()
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
}
@ -2400,6 +2512,8 @@ impl KvmVcpu {
///
fn set_vcpu_events(&self, events: &VcpuEvents) -> cpu::Result<()> {
self.fd
.lock()
.unwrap()
.set_vcpu_events(events)
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
}

View File

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

View File

@ -13,7 +13,7 @@ use crate::hypervisor;
use crate::vec_with_array_field;
use crate::vm::{self, InterruptSourceConfig, VmOps};
use crate::HypervisorType;
pub use mshv_bindings::*;
use mshv_bindings::*;
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
use std::any::Any;
use std::collections::HashMap;
@ -92,6 +92,25 @@ impl From<mshv_user_mem_region> for UserMemoryRegion {
}
}
#[cfg(target_arch = "x86_64")]
impl From<MshvClockData> for ClockData {
fn from(d: MshvClockData) -> Self {
ClockData::Mshv(d)
}
}
#[cfg(target_arch = "x86_64")]
impl From<ClockData> for MshvClockData {
fn from(ms: ClockData) -> Self {
match ms {
ClockData::Mshv(s) => s,
/* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)]
_ => unreachable!("MSHV clock data is not valid"),
}
}
}
impl From<UserMemoryRegion> for mshv_user_mem_region {
fn from(region: UserMemoryRegion) -> Self {
let mut flags: u32 = 0;
@ -1280,15 +1299,13 @@ impl cpu::Vcpu for MshvVcpu {
/// Set CPU state for x86_64 guest.
///
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
let state: VcpuMshvState = state.clone().into();
let mut state: VcpuMshvState = state.clone().into();
self.set_msrs(&state.msrs)?;
self.set_vcpu_events(&state.vcpu_events)?;
self.set_regs(&state.regs.into())?;
self.set_sregs(&state.sregs.into())?;
self.set_fpu(&state.fpu)?;
self.set_xcrs(&state.xcrs)?;
self.set_lapic(&state.lapic)?;
self.set_xsave(&state.xsave)?;
// These registers are global and needed to be set only for first VCPU
// as Microsoft Hypervisor allows setting this regsier for only one VCPU
if self.vp_index == 0 {
@ -1299,6 +1316,9 @@ impl cpu::Vcpu for MshvVcpu {
self.fd
.set_debug_regs(&state.dbg)
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
self.fd
.set_all_vp_state_components(&mut state.vp_states)
.map_err(|e| cpu::HypervisorCpuError::SetAllVpStateComponents(e.into()))?;
Ok(())
}
@ -1322,8 +1342,6 @@ impl cpu::Vcpu for MshvVcpu {
let vcpu_events = self.get_vcpu_events()?;
let mut msrs = self.msrs.clone();
self.get_msrs(&mut msrs)?;
let lapic = self.get_lapic()?;
let xsave = self.get_xsave()?;
let misc = self
.fd
.get_misc_regs()
@ -1332,6 +1350,10 @@ impl cpu::Vcpu for MshvVcpu {
.fd
.get_debug_regs()
.map_err(|e| cpu::HypervisorCpuError::GetDebugRegs(e.into()))?;
let vp_states = self
.fd
.get_all_vp_state_components()
.map_err(|e| cpu::HypervisorCpuError::GetAllVpStateComponents(e.into()))?;
Ok(VcpuMshvState {
msrs,
@ -1340,10 +1362,9 @@ impl cpu::Vcpu for MshvVcpu {
sregs: sregs.into(),
fpu,
xcrs,
lapic,
dbg,
xsave,
misc,
vp_states,
}
.into())
}
@ -1425,26 +1446,6 @@ impl cpu::Vcpu for MshvVcpu {
}
impl MshvVcpu {
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that returns the vcpu's current "xsave struct".
///
fn get_xsave(&self) -> cpu::Result<Xsave> {
self.fd
.get_xsave()
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that sets the vcpu's current "xsave struct".
///
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
self.fd
.set_xsave(xsave)
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that returns the vcpu's current "xcrs".
@ -1948,13 +1949,23 @@ impl vm::Vm for MshvVm {
/// Retrieve guest clock.
#[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> {
Ok(ClockData::Mshv)
let val = self
.fd
.get_partition_property(hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME)
.map_err(|e| vm::HypervisorVmError::GetClock(e.into()))?;
Ok(MshvClockData { ref_time: val }.into())
}
/// Set guest clock.
#[cfg(target_arch = "x86_64")]
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
Ok(())
fn set_clock(&self, data: &ClockData) -> vm::Result<()> {
let data: MshvClockData = (*data).into();
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME,
data.ref_time,
)
.map_err(|e| vm::HypervisorVmError::SetClock(e.into()))
}
/// Downcast to the underlying MshvVm type

View File

@ -19,10 +19,10 @@ use std::fmt;
///
pub use {
mshv_bindings::hv_cpuid_entry, mshv_bindings::mshv_user_mem_region as MemoryRegion,
mshv_bindings::msr_entry, mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
mshv_bindings::FloatingPointUnit, mshv_bindings::LapicState as MshvLapicState,
mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList,
mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
mshv_bindings::msr_entry, mshv_bindings::AllVpStateComponents, mshv_bindings::CpuId,
mshv_bindings::DebugRegisters, mshv_bindings::FloatingPointUnit,
mshv_bindings::LapicState as MshvLapicState, mshv_bindings::MiscRegs as MiscRegisters,
mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
mshv_bindings::SegmentRegister as MshvSegmentRegister,
mshv_bindings::SpecialRegisters as MshvSpecialRegisters,
mshv_bindings::StandardRegisters as MshvStandardRegisters, mshv_bindings::SuspendRegisters,
@ -38,10 +38,14 @@ pub struct VcpuMshvState {
pub sregs: MshvSpecialRegisters,
pub fpu: FpuState,
pub xcrs: ExtendedControlRegisters,
pub lapic: LapicState,
pub dbg: DebugRegisters,
pub xsave: Xsave,
pub misc: MiscRegisters,
pub vp_states: AllVpStateComponents,
}
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
pub struct MshvClockData {
pub ref_time: u64,
}
impl fmt::Display for VcpuMshvState {
@ -53,7 +57,7 @@ impl fmt::Display for VcpuMshvState {
msr_entries[i][1] = entry.data;
msr_entries[i][0] = entry.index as u64;
}
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- Local APIC: {:?} --- DBG: {:?} --- Xsave: {:?}",
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- DBG: {:?} --- VP States: {:?}",
msr_entries.len(),
msr_entries,
self.vcpu_events,
@ -61,9 +65,8 @@ impl fmt::Display for VcpuMshvState {
self.sregs,
self.fpu,
self.xcrs,
self.lapic,
self.dbg,
self.xsave,
self.vp_states,
)
}
}

View File

@ -11,12 +11,10 @@ libc = "0.2.153"
log = "0.4.21"
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = "1.0.197"
thiserror = "1.0.58"
versionize = "0.2.0"
versionize_derive = "0.1.6"
serde = {version = "1.0.197",features = ["derive"]}
thiserror = "1.0.60"
virtio-bindings = "0.2.2"
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1"

8
net_util/build.rs Normal file
View File

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

View File

@ -14,13 +14,13 @@ mod open_tap;
mod queue_pair;
mod tap;
use serde::{Deserialize, Serialize};
use std::io::Error as IoError;
use std::os::raw::c_uint;
use std::os::unix::io::{FromRawFd, RawFd};
use std::{io, mem, net};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::virtio_net::{
virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4,
@ -45,7 +45,7 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
#[repr(C, packed)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct VirtioNetConfig {
pub mac: [u8; 6],
pub status: u16,
@ -67,7 +67,7 @@ fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
sin_family: net_gen::AF_INET as u16,
sin_port: 0,
// SAFETY: ip_addr can be safely transmute to in_addr
sin_addr: unsafe { mem::transmute(ip_addr.octets()) },
sin_addr: unsafe { mem::transmute::<[u8; 4], net_gen::inn::in_addr>(ip_addr.octets()) },
__pad: [0; 8usize],
};

View File

@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use super::{register_listener, unregister_listener, vnet_hdr_len, Tap};
use crate::GuestMemoryMmap;
use rate_limiter::{RateLimiter, TokenType};
use std::io;
use std::num::Wrapping;
@ -12,6 +11,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use thiserror::Error;
use virtio_queue::{Queue, QueueOwnedT, QueueT};
use vm_memory::bitmap::Bitmap;
use vm_memory::{Bytes, GuestMemory};
use vm_virtio::{AccessPlatform, Translatable};
@ -35,9 +35,9 @@ impl TxVirtio {
}
}
pub fn process_desc_chain(
pub fn process_desc_chain<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
tap: &Tap,
queue: &mut Queue,
rate_limiter: &mut Option<RateLimiter>,
@ -161,9 +161,9 @@ impl RxVirtio {
}
}
pub fn process_desc_chain(
pub fn process_desc_chain<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
tap: &Tap,
queue: &mut Queue,
rate_limiter: &mut Option<RateLimiter>,
@ -350,9 +350,9 @@ pub struct NetQueuePair {
}
impl NetQueuePair {
pub fn process_tx(
pub fn process_tx<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
queue: &mut Queue,
) -> Result<bool, NetQueuePairError> {
let tx_tap_retry = self.tx.process_desc_chain(
@ -400,9 +400,9 @@ impl NetQueuePair {
.map_err(NetQueuePairError::QueueNeedsNotification)
}
pub fn process_rx(
pub fn process_rx<B: Bitmap + 'static>(
&mut self,
mem: &GuestMemoryMmap,
mem: &vm_memory::GuestMemoryMmap<B>,
queue: &mut Queue,
) -> Result<bool, NetQueuePairError> {
self.rx_desc_avail = !self.rx.process_desc_chain(

View File

@ -21,9 +21,7 @@ vmm-sys-util = "0.12.1"
libc = "0.2.153"
log = "0.4.21"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.58"
versionize = "0.2.0"
versionize_derive = "0.1.6"
thiserror = "1.0.60"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

View File

@ -409,7 +409,7 @@ impl BusDevice for PciConfigMmio {
// Only allow reads to the register boundary.
let start = offset as usize % 4;
let end = start + data.len();
if end > 4 || offset > u64::from(u32::max_value()) {
if end > 4 || offset > u64::from(u32::MAX) {
for d in data {
*d = 0xff;
}
@ -423,7 +423,7 @@ impl BusDevice for PciConfigMmio {
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if offset > u64::from(u32::max_value()) {
if offset > u64::from(u32::MAX) {
return None;
}
self.config_space_write(offset as u32, offset % 4, data);

View File

@ -7,12 +7,11 @@
use crate::device::BarReprogrammingParams;
use crate::{MsixConfig, PciInterruptPin};
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display};
use std::sync::{Arc, Mutex};
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::PciBarType;
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
// The number of 32bit registers in the config space, 4096 bytes.
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
@ -398,7 +397,7 @@ fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> {
None
}
#[derive(Debug, Default, Clone, Copy, Versionize)]
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
struct PciBar {
addr: u32,
size: u32,
@ -406,7 +405,7 @@ struct PciBar {
r#type: Option<PciBarRegionType>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct PciConfigurationState {
registers: Vec<u32>,
writable_bits: Vec<u32>,
@ -418,8 +417,6 @@ pub struct PciConfigurationState {
msix_cap_reg_idx: Option<usize>,
}
impl VersionMapped for PciConfigurationState {}
/// Contains the configuration space of a PCI node.
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
/// The configuration space is accessed with DWORD reads and writes from the guest.
@ -437,7 +434,7 @@ pub struct PciConfiguration {
}
/// See pci_regs.h in kernel
#[derive(Copy, Clone, PartialEq, Eq, Versionize, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum PciBarRegionType {
Memory32BitRegion = 0,
IoRegion = 0x01,
@ -746,7 +743,7 @@ impl PciConfiguration {
.ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
match config.region_type {
PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
if end_addr > u64::from(u32::max_value()) {
if end_addr > u64::from(u32::MAX) {
return Err(Error::BarAddressInvalid(config.addr, config.size));
}
@ -760,10 +757,6 @@ impl PciConfiguration {
return Err(Error::BarInvalid64(bar_idx));
}
if end_addr > u64::max_value() {
return Err(Error::BarAddressInvalid(config.addr, config.size));
}
if self.bars[bar_idx + 1].used {
return Err(Error::BarInUse64(bar_idx));
}
@ -821,7 +814,7 @@ impl PciConfiguration {
.checked_add(config.size - 1)
.ok_or(Error::RomBarAddressInvalid(config.addr, config.size))?;
if end_addr > u64::from(u32::max_value()) {
if end_addr > u64::from(u32::MAX) {
return Err(Error::RomBarAddressInvalid(config.addr, config.size));
}
@ -1072,7 +1065,7 @@ impl Snapshottable for PciConfiguration {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -4,15 +4,14 @@
//
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use std::io;
use std::sync::Arc;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::{
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
// MSI control masks
const MSI_CTL_ENABLE: u16 = 0x1;
@ -47,7 +46,7 @@ pub enum Error {
pub const MSI_CONFIG_ID: &str = "msi_config";
#[derive(Clone, Copy, Default, Versionize)]
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
pub struct MsiCap {
// Message Control Register
// 0: MSI enable.
@ -172,13 +171,11 @@ impl MsiCap {
}
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct MsiConfigState {
cap: MsiCap,
}
impl VersionMapped for MsiConfigState {}
pub struct MsiConfig {
pub cap: MsiCap,
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
@ -294,6 +291,6 @@ impl Snapshottable for MsiConfig {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -5,16 +5,16 @@
use crate::{PciCapability, PciCapabilityId};
use byteorder::{ByteOrder, LittleEndian};
use serde::Deserialize;
use serde::Serialize;
use std::io;
use std::result;
use std::sync::Arc;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::{
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
};
use vm_memory::ByteValued;
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
@ -35,7 +35,7 @@ pub enum Error {
UpdateInterruptRoute(io::Error),
}
#[derive(Debug, Clone, Versionize, Eq, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct MsixTableEntry {
pub msg_addr_lo: u32,
pub msg_addr_hi: u32,
@ -60,7 +60,7 @@ impl Default for MsixTableEntry {
}
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct MsixConfigState {
table_entries: Vec<MsixTableEntry>,
pba_entries: Vec<u64>,
@ -68,8 +68,6 @@ pub struct MsixConfigState {
enabled: bool,
}
impl VersionMapped for MsixConfigState {}
pub struct MsixConfig {
pub table_entries: Vec<MsixTableEntry>,
pub pba_entries: Vec<u64>,
@ -436,13 +434,13 @@ impl Snapshottable for MsixConfig {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
#[allow(dead_code)]
#[repr(packed)]
#[derive(Clone, Copy, Default, Versionize)]
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
pub struct MsixCap {
// Message Control Register
// 10-0: MSI-X Table size

View File

@ -15,6 +15,7 @@ use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use hypervisor::HypervisorVmError;
use libc::{sysconf, _SC_PAGESIZE};
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::collections::{BTreeMap, HashMap};
use std::io;
@ -22,8 +23,6 @@ use std::os::unix::io::AsRawFd;
use std::ptr::null_mut;
use std::sync::{Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vfio_bindings::bindings::vfio::*;
use vfio_ioctls::{
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
@ -38,9 +37,7 @@ use vm_device::interrupt::{
};
use vm_device::{BusDevice, Resource};
use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
pub(crate) const VFIO_COMMON_ID: &str = "vfio_common";
@ -95,7 +92,7 @@ enum InterruptUpdateAction {
DisableMsix,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
struct IntxState {
enabled: bool,
}
@ -105,7 +102,7 @@ pub(crate) struct VfioIntx {
enabled: bool,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
struct MsiState {
cap: MsiCap,
cap_offset: u32,
@ -137,7 +134,7 @@ impl VfioMsi {
}
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
struct MsixState {
cap: MsixCap,
cap_offset: u32,
@ -440,15 +437,13 @@ impl Vfio for VfioDeviceWrapper {
}
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
struct VfioCommonState {
intx_state: Option<IntxState>,
msi_state: Option<MsiState>,
msix_state: Option<MsixState>,
}
impl VersionMapped for VfioCommonState {}
pub(crate) struct ConfigPatch {
mask: u32,
patch: u32,
@ -476,13 +471,12 @@ impl VfioCommon {
x_nv_gpudirect_clique: Option<u8>,
) -> Result<Self, VfioPciError> {
let pci_configuration_state =
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
.map_err(|e| {
VfioPciError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
))
})?;
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
VfioPciError::RetrievePciConfigurationState(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
))
})?;
let configuration = PciConfiguration::new(
0,
@ -515,7 +509,7 @@ impl VfioCommon {
let state: Option<VfioCommonState> = snapshot
.as_ref()
.map(|s| s.to_versioned_state())
.map(|s| s.to_state())
.transpose()
.map_err(|e| {
VfioPciError::RetrieveVfioCommonState(anyhow!(
@ -523,20 +517,20 @@ impl VfioCommon {
e
))
})?;
let msi_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSI_CONFIG_ID)
.map_err(|e| {
let msi_state =
vm_migration::state_from_id(snapshot.as_ref(), MSI_CONFIG_ID).map_err(|e| {
VfioPciError::RetrieveMsiConfigState(anyhow!(
"Failed to get MsiConfigState from Snapshot: {}",
e
))
})?;
let msix_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID)
.map_err(|e| {
VfioPciError::RetrieveMsixConfigState(anyhow!(
"Failed to get MsixConfigState from Snapshot: {}",
e
))
})?;
let msix_state =
vm_migration::state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID).map_err(|e| {
VfioPciError::RetrieveMsixConfigState(anyhow!(
"Failed to get MsixConfigState from Snapshot: {}",
e
))
})?;
if let Some(state) = state.as_ref() {
vfio_common.set_state(state, msi_state, msix_state)?;
@ -1388,7 +1382,7 @@ impl Snapshottable for VfioCommon {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let mut vfio_common_snapshot = Snapshot::new_from_versioned_state(&self.state())?;
let mut vfio_common_snapshot = Snapshot::new_from_state(&self.state())?;
// Snapshot PciConfiguration
vfio_common_snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);

View File

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

View File

@ -11,5 +11,5 @@ dirs = "5.0.1"
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
test_infra = { path = "../test_infra" }
thiserror = "1.0.58"
thiserror = "1.0.60"
wait-timeout = "0.2.0"

View File

@ -7,5 +7,5 @@ edition = "2021"
epoll = "4.3.3"
libc = "0.2.153"
log = "0.4.21"
thiserror = "1.0.58"
thiserror = "1.0.60"
vmm-sys-util = "0.12.1"

View File

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

View File

@ -662,8 +662,8 @@ pub(crate) mod tests {
// limiter should not be blocked
assert!(!l.is_blocked());
// limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Ops));
assert!(l.consume(u64::max_value(), TokenType::Bytes));
assert!(l.consume(u64::MAX, TokenType::Ops));
assert!(l.consume(u64::MAX, TokenType::Bytes));
// calling the handler without there having been an event should error
assert!(l.event_handler().is_err());
assert_eq!(
@ -721,7 +721,7 @@ pub(crate) mod tests {
assert!(l.as_raw_fd() > 0);
// ops/s limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Ops));
assert!(l.consume(u64::MAX, TokenType::Ops));
// do full 1000 bytes
assert!(l.consume(1000, TokenType::Bytes));
@ -754,7 +754,7 @@ pub(crate) mod tests {
assert!(l.as_raw_fd() > 0);
// bytes/s limiter should be disabled so consume(whatever) should work
assert!(l.consume(u64::max_value(), TokenType::Bytes));
assert!(l.consume(u64::MAX, TokenType::Bytes));
// do full 1000 ops
assert!(l.consume(1000, TokenType::Ops));

View File

@ -1,3 +1,10 @@
- [v39.0](#v390)
- [Variable Sizing of PCI Apertures for Segments](#variable-sizing-of-pci-apertures-for-segments)
- [Direct Booting with bzImages](#direct-booting-with-bzimages)
- [Support for NVIDIA GPUDirect P2P Support](#support-for-nvidia-gpudirect-p2p-support)
- [Guest NMI Injection Support](#guest-nmi-injection-support)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [v38.0](#v380)
- [Group Rate Limiter on Block Devices](#group-rate-limiter-on-block-devices)
- [CPU Pinning Support for Block Device Worker Thread](#cpu-pinning-support-for-block-device-worker-thread)
@ -5,16 +12,16 @@
- [New 'debug-console' Device](#new-debug-console-device)
- [Improved VFIO Device Support](#improved-vfio-device-support)
- [Extended CPU Affinity Support](#extended-cpu-affinity-support)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [v37.0](#v370)
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [Multiple PCI segments Support for 32-bit VFIO devices](#multiple-pci-segments-support-for-32-bit-vfio-devices)
- [Configurable Named TAP Devices](#configurable-named-tap-devices)
- [TTY Output from Both Serial Device and Virtio Console](#tty-output-from-both-serial-device-and-virtio-console)
- [Faster VM Restoration from Snapshots](#faster-vm-restoration-from-snapshots)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-2)
- [v36.0](#v360)
- [Command Line Changes](#command-line-changes)
- [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli)
@ -23,31 +30,31 @@
- [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port)
- [AIO Backend for Block Devices](#aio-backend-for-block-devices)
- [Documentation Improvements](#documentation-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-2)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-3)
- [v35.0](#v350)
- [`virtio-vsock` Support for Linux Guest Kernel v6.3+](#virtio-vsock-support-for-linux-guest-kernel-v63)
- [User Specified Serial Number for `virtio-block`](#user-specified-serial-number-for-virtio-block)
- [vCPU TSC Frequency Included in Migration State](#vcpu-tsc-frequency-included-in-migration-state)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-3)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-4)
- [v34.0](#v340)
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-4)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [v33.0](#v330)
- [D-Bus based API](#d-bus-based-api)
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [v32.0](#v320)
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
- [API Changes](#api-changes)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [v31.1](#v311)
- [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
@ -55,15 +62,15 @@
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
- [Documentation Improvements](#documentation-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [v30.0](#v300)
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
- [Heap Profiling Support](#heap-profiling-support)
- [Documentation Improvements](#documentation-improvements-2)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [v28.2](#v282)
- [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
@ -73,10 +80,10 @@
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
- [TCP Offload Control](#tcp-offload-control)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Removals](#removals)
- [Deprecations](#deprecations)
- [Contributors](#contributors-9)
- [Contributors](#contributors-10)
- [v28.1](#v281)
- [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder)
@ -84,9 +91,9 @@
- [Virtualised TPM Support](#virtualised-tpm-support)
- [Transparent Huge Page Support](#transparent-huge-page-support)
- [README Quick Start Improved](#readme-quick-start-improved)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Removals](#removals-1)
- [Contributors](#contributors-10)
- [Contributors](#contributors-11)
- [v27.0](#v270)
- [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages)
@ -95,41 +102,41 @@
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
- [GDB Support for AArch64](#gdb-support-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-11)
- [Contributors](#contributors-12)
- [v26.0](#v260)
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Deprecations](#deprecations-2)
- [Removals](#removals-2)
- [Contributors](#contributors-12)
- [Contributors](#contributors-13)
- [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Removals](#removals-3)
- [Contributors](#contributors-13)
- [Contributors](#contributors-14)
- [v24.0](#v240)
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
- [Sparse Mmap support](#sparse-mmap-support)
- [Expose Platform Serial Number](#expose-platform-serial-number)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Notable Bug Fixes](#notable-bug-fixes-15)
- [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website)
- [Contributors](#contributors-14)
- [Contributors](#contributors-15)
- [v23.1](#v231)
- [v23.0](#v230)
- [vDPA Support](#vdpa-support)
- [Updated OS Support list](#updated-os-support-list)
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
- [`AMX` Support](#amx-support)
- [Notable Bug Fixes](#notable-bug-fixes-15)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Deprecations](#deprecations-4)
- [Contributors](#contributors-15)
- [Contributors](#contributors-16)
- [v22.1](#v221)
- [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support)
@ -140,13 +147,13 @@
- [PMU Support for AArch64](#pmu-support-for-aarch64)
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Contributors](#contributors-16)
- [Notable Bug Fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-17)
- [v21.0](#v210)
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
- [Notable Bug fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-17)
- [Notable Bug fixes](#notable-bug-fixes-18)
- [Contributors](#contributors-18)
- [v20.2](#v202)
- [v20.1](#v201)
- [v20.0](#v200)
@ -155,8 +162,8 @@
- [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code)
- [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-18)
- [Contributors](#contributors-18)
- [Notable bug fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-19)
- [v19.0](#v190)
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
- [PCI boot time optimisations](#pci-boot-time-optimisations)
@ -164,8 +171,8 @@
- [Live migration enhancements](#live-migration-enhancements)
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
- [Notable bug fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-19)
- [Notable bug fixes](#notable-bug-fixes-20)
- [Contributors](#contributors-20)
- [v18.0](#v180)
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
@ -175,23 +182,23 @@
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
- [Power button support on AArch64](#power-button-support-on-aarch64)
- [Notable bug fixes](#notable-bug-fixes-20)
- [Contributors](#contributors-20)
- [Notable bug fixes](#notable-bug-fixes-21)
- [Contributors](#contributors-21)
- [v17.0](#v170)
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
- [Improved SGX support](#improved-sgx-support)
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
- [Notable bug fixes](#notable-bug-fixes-21)
- [Contributors](#contributors-21)
- [Notable bug fixes](#notable-bug-fixes-22)
- [Contributors](#contributors-22)
- [v16.0](#v160)
- [Improved live migration support](#improved-live-migration-support)
- [Improved `vhost-user` support](#improved-vhost-user-support)
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
- [Notable bug fixes](#notable-bug-fixes-22)
- [Notable bug fixes](#notable-bug-fixes-23)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors-22)
- [Contributors](#contributors-23)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@ -199,7 +206,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5)
- [Contributors](#contributors-23)
- [Contributors](#contributors-24)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@ -209,7 +216,7 @@
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
- [Block device rate limiting](#block-device-rate-limiting)
- [Deprecations](#deprecations-6)
- [Contributors](#contributors-24)
- [Contributors](#contributors-25)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@ -217,13 +224,13 @@
- [VHD disk image support](#vhd-disk-image-support)
- [Improved Virtio device threading](#improved-virtio-device-threading)
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
- [Contributors](#contributors-25)
- [Contributors](#contributors-26)
- [v0.12.0](#v0120)
- [ARM64 enhancements](#arm64-enhancements)
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
- [Enhanced "info" API](#enhanced-info-api)
- [Contributors](#contributors-26)
- [Contributors](#contributors-27)
- [v0.11.0](#v0110)
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
- [Windows Guest Support](#windows-guest-support)
@ -235,15 +242,15 @@
- [Default Log Level Changed](#default-log-level-changed)
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
- [Notable Bug Fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-27)
- [Notable Bug Fixes](#notable-bug-fixes-24)
- [Contributors](#contributors-28)
- [v0.10.0](#v0100)
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
- [Memory Zones](#memory-zones)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
- [Notable Bug Fixes](#notable-bug-fixes-24)
- [Contributors](#contributors-28)
- [Notable Bug Fixes](#notable-bug-fixes-25)
- [Contributors](#contributors-29)
- [v0.9.0](#v090)
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
- [Block and Network Device Statistics](#block-and-network-device-statistics)
@ -256,17 +263,17 @@
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
- [Intel SGX Support](#intel-sgx-support)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-25)
- [Contributors](#contributors-29)
- [Notable Bug Fixes](#notable-bug-fixes-26)
- [Contributors](#contributors-30)
- [v0.8.0](#v080)
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
- [Experimental ARM64 Support](#experimental-arm64-support)
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-26)
- [Notable Bug Fixes](#notable-bug-fixes-27)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-30)
- [Contributors](#contributors-31)
- [v0.7.0](#v070)
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
- [Alternative `libc` Support](#alternative-libc-support)
@ -276,14 +283,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-31)
- [Contributors](#contributors-32)
- [v0.6.0](#v060)
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
- [Command Line Interface](#command-line-interface)
- [PVH Boot](#pvh-boot)
- [Contributors](#contributors-32)
- [Contributors](#contributors-33)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@ -291,7 +298,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-33)
- [Contributors](#contributors-34)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@ -300,7 +307,7 @@
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
- [PCI BAR reprogramming](#pci-bar-reprogramming)
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
- [Contributors](#contributors-34)
- [Contributors](#contributors-35)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@ -327,6 +334,77 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# v39.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v39.0. The following user visible changes have been made:
### Variable Sizing of PCI Apertures for Segments
It is now possible to use `--pci-segment` to adjust the aperture size that
devices 32-bit and 64-bit PCI device BARs will be allocated from. Previously
the address space was equally distributed across all the segments which may
leave insufficient space for devices that require a large 32-bit space. With
this change the weighting per segment can be adjusted. (#6387)
### Direct Booting with bzImages
Support for directly booting Linux from bzImages has been added.(#6200)
### Support for NVIDIA GPUDirect P2P Support
The `x_nv_gpudirect_clique` option was added to `--device` to allow the
configuration of device P2P support with NVIDIA GPUs. (#6235)
### Guest NMI Injection Support
A new API endpoint and `ch-remote` option added for injecting an NMI into the
guest. (#6047)
### Notable Bug Fixes
* Workaround for kernel bug affecting guest IRQ masking on AMD (#6353)
* Correctly cleanup `sigwinch_listener` process (#6208)
* Graceful shutdown of HTTP API thread (#6248, #6247)
* Fix `queue_affinity` option in OpenAPI metadata (#6268)
* Fix documentation to indicate only stream mode is supported by `virtio-vsock`
(#6306)
* Fix `virtio-fs` tag validation (#6358, #6359)
* Add missing `pvpanic` device to OpenAPI metadata (#6372)
* Fixes for nested virtualization with VFIO devices (#6110, #6298, #6297,
#6319)
* Fix for backing file for `virtio-mem` regions with snapshot/restore (#6337,
#6338)
* Explicitly mark FDs used for network devices as invalid across
snapshot/restore (#6332, #6286)
* Improve `event-monitor` events around reboot (#6277, #6274)
* Fix potential deadlock around paused devices during live migration (#6293)
* Fix panic when running `ch-remote` with no subcommand (#6230)
* Fix hotplug of `virtio` devices after snapshot/restore and live migration
(#6326, #6265)
### Contributors
Many thanks to everyone who has contributed to our release:
* Alexandru Matei <alexandru.matei@uipath.com>
* Andrew Carp <acarp@crusoeenergy.com>
* Bo Chen <chen.bo@intel.com>
* Bouke van der Bijl <i@bou.ke>
* Chris Webb <chris@arachsys.com>
* Jinank Jain <jinankjain@microsoft.com>
* Lucas Jacques <contact@lucasjacques.com>
* Muminul Islam <muislam@microsoft.com>
* Nuno Das Neves <nudasnev@microsoft.com>
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
* Rob Bradford <rbradford@rivosinc.com>
* Ruslan Mstoi <ruslan.mstoi@intel.com>
* Stefan Nuernberger <stefan.nuernberger@cyberus-technology.de>
* Thomas Barrett <tbarrett@crusoeenergy.com>
* Wei Liu <liuwe@microsoft.com>
* Yi Wang <foxywang@tencent.com>
# v38.0
This release has been tracked in our [roadmap

View File

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

View File

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

View File

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

View File

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

View File

@ -355,6 +355,13 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("pci-segment")
.long("pci-segment")
.help(config::PciSegmentConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("watchdog")
.long("watchdog")
@ -934,6 +941,7 @@ mod unit_tests {
watchdog: false,
#[cfg(feature = "guest_debug")]
gdb: false,
pci_segments: None,
platform: None,
tpm: None,
preserved_fds: None,

View File

@ -2344,7 +2344,10 @@ fn make_guest_panic(guest: &Guest) {
}
mod common_parallel {
use std::{fs::OpenOptions, io::SeekFrom};
use std::{
fs::{remove_dir_all, OpenOptions},
io::SeekFrom,
};
use crate::*;
@ -6012,10 +6015,10 @@ mod common_parallel {
"id={},tap=,mac={},ip={},mask=255.255.255.0",
net_id, guest.network.guest_mac, guest.network.host_ip
);
let mut mem_params = "size=4G";
let mut mem_params = "size=2G";
if use_hotplug {
mem_params = "size=4G,hotplug_method=virtio-mem,hotplug_size=32G"
mem_params = "size=2G,hotplug_method=virtio-mem,hotplug_size=32G"
}
let cloudinit_params = format!(
@ -6059,7 +6062,7 @@ mod common_parallel {
// Check the number of vCPUs
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4);
// Check the guest RAM
assert!(guest.get_total_memory().unwrap_or_default() > 3_840_000);
assert!(guest.get_total_memory().unwrap_or_default() > 1_920_000);
if use_hotplug {
// Increase guest RAM with virtio-mem
resize_command(
@ -6229,6 +6232,9 @@ mod common_parallel {
&event_path_restored
));
// Remove the snapshot dir
let _ = remove_dir_all(snapshot_dir.as_str());
let r = std::panic::catch_unwind(|| {
// Resume the VM
assert!(remote_command(&api_socket_restored, "resume", None));
@ -6257,7 +6263,7 @@ mod common_parallel {
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4);
let total_memory = guest.get_total_memory().unwrap_or_default();
if !use_hotplug {
assert!(guest.get_total_memory().unwrap_or_default() > 3_840_000);
assert!(total_memory > 1_920_000);
} else {
assert!(total_memory > 4_800_000);
assert!(total_memory < 5_760_000);
@ -9718,18 +9724,6 @@ mod live_migration {
_test_live_migration(false, true)
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_live_migration_numa() {
_test_live_migration_numa(false, false)
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_live_migration_numa_local() {
_test_live_migration_numa(false, true)
}
#[test]
fn test_live_migration_watchdog() {
_test_live_migration_watchdog(false, false)
@ -9740,6 +9734,32 @@ mod live_migration {
_test_live_migration_watchdog(false, true)
}
#[test]
fn test_live_upgrade_basic() {
_test_live_migration(true, false)
}
#[test]
fn test_live_upgrade_local() {
_test_live_migration(true, true)
}
#[test]
fn test_live_upgrade_watchdog() {
_test_live_migration_watchdog(true, false)
}
#[test]
fn test_live_upgrade_watchdog_local() {
_test_live_migration_watchdog(true, true)
}
}
mod live_migration_sequential {
use super::*;
// NUMA & baalloon live migration tests are large so run sequentially
#[test]
fn test_live_migration_balloon() {
_test_live_migration_balloon(false, false)
@ -9751,61 +9771,39 @@ mod live_migration {
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_basic() {
_test_live_migration(true, false)
fn test_live_upgrade_balloon() {
_test_live_migration_balloon(true, false)
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_local() {
_test_live_migration(true, true)
fn test_live_upgrade_balloon_local() {
_test_live_migration_balloon(true, true)
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_live_migration_numa() {
_test_live_migration_numa(false, false)
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_live_migration_numa_local() {
_test_live_migration_numa(false, true)
}
#[test]
#[ignore = "See #6134"]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_numa() {
_test_live_migration_numa(true, false)
}
#[test]
#[ignore = "See #6134"]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_numa_local() {
_test_live_migration_numa(true, true)
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_watchdog() {
_test_live_migration_watchdog(true, false)
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_watchdog_local() {
_test_live_migration_watchdog(true, true)
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_balloon() {
_test_live_migration_balloon(true, false)
}
#[test]
#[ignore = "See #6134"]
fn test_live_upgrade_balloon_local() {
_test_live_migration_balloon(true, true)
}
}
mod live_migration_sequential {
#[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))]
use super::*;
// Require to run ovs-dpdk tests sequentially because they rely on the same ovs-dpdk setup
#[test]
#[ignore = "See #5532"]

View File

@ -13,9 +13,9 @@ epoll = "4.3.3"
libc = "0.2.153"
log = "0.4.21"
option_parser = { path = "../option_parser" }
vhost = { version = "0.10.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.13.1"
vhost = { version = "0.11.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.15.0"
virtio-bindings = "0.2.2"
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-memory = "0.14.1"
vmm-sys-util = "0.12.1"

View File

@ -32,16 +32,18 @@ use std::time::Instant;
use std::{convert, error, fmt, io};
use vhost::vhost_user::message::*;
use vhost::vhost_user::Listener;
use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringState, VringT};
use vhost_user_backend::{
bitmap::BitmapMmapRegion, VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringState, VringT,
};
use virtio_bindings::virtio_blk::*;
use virtio_bindings::virtio_config::VIRTIO_F_VERSION_1;
use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use virtio_queue::QueueT;
use vm_memory::GuestAddressSpace;
use vm_memory::{bitmap::AtomicBitmap, ByteValued, Bytes, GuestMemoryAtomic};
use vm_memory::{ByteValued, Bytes, GuestMemoryAtomic};
use vmm_sys_util::{epoll::EventSet, eventfd::EventFd};
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<BitmapMmapRegion>;
const SECTOR_SHIFT: u8 = 9;
const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
@ -300,7 +302,7 @@ impl VhostUserBlkBackend {
}
impl VhostUserBackendMut for VhostUserBlkBackend {
type Bitmap = AtomicBitmap;
type Bitmap = BitmapMmapRegion;
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
fn num_queues(&self) -> usize {

View File

@ -13,8 +13,8 @@ libc = "0.2.153"
log = "0.4.21"
net_util = { path = "../net_util" }
option_parser = { path = "../option_parser" }
vhost = { version = "0.10.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.13.1"
vhost = { version = "0.11.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.15.0"
virtio-bindings = "0.2.2"
vm-memory = "0.14.1"
vmm-sys-util = "0.12.1"

View File

@ -22,14 +22,15 @@ use std::process;
use std::sync::{Arc, Mutex, RwLock};
use vhost::vhost_user::message::*;
use vhost::vhost_user::Listener;
use vhost_user_backend::bitmap::BitmapMmapRegion;
use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringT};
use virtio_bindings::virtio_config::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1};
use virtio_bindings::virtio_net::*;
use vm_memory::GuestAddressSpace;
use vm_memory::{bitmap::AtomicBitmap, GuestMemoryAtomic};
use vm_memory::GuestMemoryAtomic;
use vmm_sys_util::{epoll::EventSet, eventfd::EventFd};
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<BitmapMmapRegion>;
pub type Result<T> = std::result::Result<T, Error>;
type VhostUserBackendResult<T> = std::result::Result<T, std::io::Error>;
@ -158,7 +159,7 @@ impl VhostUserNetBackend {
}
impl VhostUserBackendMut for VhostUserNetBackend {
type Bitmap = AtomicBitmap;
type Bitmap = BitmapMmapRegion;
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
fn num_queues(&self) -> usize {

View File

@ -6,6 +6,7 @@ edition = "2021"
[features]
default = []
sev_snp = []
[dependencies]
anyhow = "1.0.81"
@ -23,13 +24,12 @@ rate_limiter = { path = "../rate_limiter" }
seccompiler = "0.4.0"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
serde_with = { version = "3.7.0", default-features = false, features = ["macros"] }
serial_buffer = { path = "../serial_buffer" }
thiserror = "1.0.58"
versionize = "0.2.0"
versionize_derive = "0.1.6"
vhost = { version = "0.10.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] }
thiserror = "1.0.60"
vhost = { version = "0.11.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] }
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

8
virtio-devices/build.rs Normal file
View File

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

View File

@ -22,23 +22,20 @@ use crate::{
};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::io::{self, Write};
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::{atomic::AtomicBool, Arc, Barrier};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_allocator::page_size::{align_page_size_down, get_page_size};
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryError, GuestMemoryRegion,
};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
const QUEUE_SIZE: u16 = 128;
@ -89,7 +86,7 @@ pub enum Error {
// Got from include/uapi/linux/virtio_balloon.h
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct VirtioBalloonConfig {
// Number of pages host wants Guest to give up.
num_pages: u32,
@ -418,15 +415,13 @@ impl EpollHelperHandler for BalloonEpollHandler {
}
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct BalloonState {
pub avail_features: u64,
pub acked_features: u64,
pub config: VirtioBalloonConfig,
}
impl VersionMapped for BalloonState {}
// Virtio device for exposing entropy to the guest OS through virtio.
pub struct Balloon {
common: VirtioCommon,
@ -672,7 +667,7 @@ impl Snapshottable for Balloon {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Balloon {}

View File

@ -25,6 +25,7 @@ use block::{
use rate_limiter::group::{RateLimiterGroup, RateLimiterGroupHandle};
use rate_limiter::TokenType;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::VecDeque;
@ -37,13 +38,10 @@ use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Barrier};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::virtio_blk::*;
use virtio_bindings::virtio_config::*;
use virtio_queue::{Queue, QueueOwnedT, QueueT};
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryError};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::AccessPlatform;
use vmm_sys_util::eventfd::EventFd;
@ -552,7 +550,7 @@ pub struct Block {
queue_affinity: BTreeMap<u16, Vec<usize>>,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct BlockState {
pub disk_path: String,
pub disk_nsectors: u64,
@ -561,8 +559,6 @@ pub struct BlockState {
pub config: VirtioBlockConfig,
}
impl VersionMapped for BlockState {}
impl Block {
/// Create a new virtio block device that operates on the given file.
#[allow(clippy::too_many_arguments)]
@ -916,7 +912,7 @@ impl Snapshottable for Block {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Block {}

View File

@ -14,6 +14,7 @@ use crate::VirtioInterrupt;
use anyhow::anyhow;
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use serial_buffer::SerialBuffer;
use std::cmp;
use std::collections::VecDeque;
@ -25,11 +26,8 @@ use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::eventfd::EventFd;
@ -67,7 +65,7 @@ enum Error {
QueueAddUsed(virtio_queue::Error),
}
#[derive(Copy, Clone, Debug, Versionize)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[repr(C, packed)]
pub struct VirtioConsoleConfig {
cols: u16,
@ -593,7 +591,7 @@ pub struct Console {
exit_evt: EventFd,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct ConsoleState {
avail_features: u64,
acked_features: u64,
@ -620,8 +618,6 @@ fn get_win_size(tty: &dyn AsRawFd) -> (u16, u16) {
(ws.cols, ws.rows)
}
impl VersionMapped for ConsoleState {}
impl Console {
/// Create a new virtio console device
pub fn new(
@ -825,7 +821,7 @@ impl Snapshottable for Console {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Console {}

View File

@ -13,6 +13,7 @@ use crate::GuestMemoryMmap;
use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::io;
use std::mem::size_of;
@ -22,15 +23,12 @@ use std::result;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier, Mutex, RwLock};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
GuestMemoryError, GuestMemoryLoadGuard,
};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::AccessPlatform;
use vmm_sys_util::eventfd::EventFd;
@ -781,7 +779,7 @@ impl EpollHelperHandler for IommuEpollHandler {
}
}
#[derive(Clone, Copy, Debug, Versionize)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
struct Mapping {
gpa: u64,
size: u64,
@ -905,7 +903,7 @@ pub struct Iommu {
type EndpointsState = Vec<(u32, u32)>;
type DomainsState = Vec<(u32, (Vec<(u64, Mapping)>, bool))>;
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct IommuState {
avail_features: u64,
acked_features: u64,
@ -913,8 +911,6 @@ pub struct IommuState {
domains: DomainsState,
}
impl VersionMapped for IommuState {}
impl Iommu {
pub fn new(
id: String,
@ -1154,7 +1150,7 @@ impl Snapshottable for Iommu {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Iommu {}

View File

@ -25,6 +25,7 @@ use crate::{GuestMemoryMmap, GuestRegionMmap};
use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::io;
use std::mem::size_of;
@ -34,8 +35,6 @@ use std::sync::atomic::AtomicBool;
use std::sync::mpsc;
use std::sync::{Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{
@ -43,9 +42,7 @@ use vm_memory::{
GuestMemoryError, GuestMemoryLoadGuard, GuestMemoryRegion,
};
use vm_migration::protocol::MemoryRangeTable;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
const QUEUE_SIZE: u16 = 128;
@ -170,7 +167,7 @@ struct VirtioMemResp {
unsafe impl ByteValued for VirtioMemResp {}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct VirtioMemConfig {
// Block size and alignment. Cannot change.
block_size: u64,
@ -338,7 +335,7 @@ impl Request {
}
}
#[derive(Clone, Versionize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct BlocksState {
bitmap: Vec<bool>,
}
@ -688,7 +685,7 @@ pub enum VirtioMemMappingSource {
Device(u32),
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct MemState {
pub avail_features: u64,
pub acked_features: u64,
@ -696,8 +693,6 @@ pub struct MemState {
pub blocks_state: BlocksState,
}
impl VersionMapped for MemState {}
pub struct Mem {
common: VirtioCommon,
id: String,
@ -1013,7 +1008,7 @@ impl Snapshottable for Mem {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Mem {}

View File

@ -24,6 +24,7 @@ use net_util::{
NetQueuePair, OpenTapError, RxVirtio, Tap, TapError, TxVirtio, VirtioNetConfig,
};
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::num::Wrapping;
@ -34,14 +35,11 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier};
use std::thread;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::virtio_config::*;
use virtio_bindings::virtio_net::*;
use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use virtio_queue::{Queue, QueueT};
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::AccessPlatform;
use vmm_sys_util::eventfd::EventFd;
@ -423,7 +421,7 @@ pub struct Net {
exit_evt: EventFd,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct NetState {
pub avail_features: u64,
pub acked_features: u64,
@ -431,8 +429,6 @@ pub struct NetState {
pub queue_size: Vec<u16>,
}
impl VersionMapped for NetState {}
impl Net {
/// Create a new virtio network device with the given TAP interface.
#[allow(clippy::too_many_arguments)]
@ -886,7 +882,7 @@ impl Snapshottable for Net {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl Transportable for Net {}

View File

@ -18,6 +18,7 @@ use crate::{GuestMemoryMmap, MmapRegion};
use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io;
use std::mem::size_of;
@ -26,14 +27,11 @@ use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
GuestMemoryError, GuestMemoryLoadGuard,
};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::eventfd::EventFd;
@ -48,7 +46,7 @@ const VIRTIO_PMEM_RESP_TYPE_EIO: u32 = 1;
// New descriptors are pending on the virtio queue.
const QUEUE_AVAIL_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
#[repr(C)]
struct VirtioPmemConfig {
start: u64,
@ -279,15 +277,13 @@ pub struct Pmem {
_region: MmapRegion,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct PmemState {
avail_features: u64,
acked_features: u64,
config: VirtioPmemConfig,
}
impl VersionMapped for PmemState {}
impl Pmem {
#[allow(clippy::too_many_arguments)]
pub fn new(
@ -468,7 +464,7 @@ impl Snapshottable for Pmem {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -16,6 +16,7 @@ use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io;
use std::os::unix::io::AsRawFd;
@ -23,11 +24,8 @@ use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_memory::{GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::eventfd::EventFd;
@ -160,14 +158,12 @@ pub struct Rng {
exit_evt: EventFd,
}
#[derive(Versionize)]
#[derive(Deserialize, Serialize)]
pub struct RngState {
pub avail_features: u64,
pub acked_features: u64,
}
impl VersionMapped for RngState {}
impl Rng {
/// Create a new virtio rng device that gets random data from /dev/urandom.
pub fn new(
@ -326,7 +322,7 @@ impl Snapshottable for Rng {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -8,17 +8,16 @@
use crate::VirtioDevice;
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use std::sync::atomic::{AtomicU16, Ordering};
use std::sync::{Arc, Mutex};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
use vm_virtio::AccessPlatform;
pub const VIRTIO_PCI_COMMON_CONFIG_ID: &str = "virtio_pci_common_config";
#[derive(Clone, Versionize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct VirtioPciCommonConfigState {
pub driver_status: u8,
pub config_generation: u8,
@ -29,8 +28,6 @@ pub struct VirtioPciCommonConfigState {
pub msix_queues: Vec<u16>,
}
impl VersionMapped for VirtioPciCommonConfigState {}
/// Contains the data for reading and writing the common configuration structure of a virtio PCI
/// device.
///
@ -321,7 +318,7 @@ impl Snapshottable for VirtioPciCommonConfig {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -20,6 +20,7 @@ use pci::{
PciCapability, PciCapabilityId, PciClassCode, PciConfiguration, PciDevice, PciDeviceError,
PciHeaderType, PciMassStorageSubclass, PciNetworkControllerSubclass, PciSubclass,
};
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::cmp;
use std::io::Write;
@ -27,8 +28,6 @@ use std::ops::Deref;
use std::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
use std::sync::{Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::dma_mapping::ExternalDmaMapping;
@ -37,9 +36,7 @@ use vm_device::interrupt::{
};
use vm_device::{BusDevice, PciBarType, Resource};
use vm_memory::{Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, Le32};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::AccessPlatform;
use vmm_sys_util::eventfd::EventFd;
@ -263,7 +260,7 @@ const NOTIFY_OFF_MULTIPLIER: u32 = 4; // A dword per notification address.
const VIRTIO_PCI_VENDOR_ID: u16 = 0x1af4;
const VIRTIO_PCI_DEVICE_ID_BASE: u16 = 0x1040; // Add to device type to get device ID.
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
struct QueueState {
max_size: u16,
size: u16,
@ -273,7 +270,7 @@ struct QueueState {
used_ring: u64,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct VirtioPciDeviceState {
device_activated: bool,
queues: Vec<QueueState>,
@ -282,8 +279,6 @@ pub struct VirtioPciDeviceState {
cap_pci_cfg: Vec<u8>,
}
impl VersionMapped for VirtioPciDeviceState {}
pub struct VirtioPciDeviceActivator {
interrupt: Option<Arc<dyn VirtioInterrupt>>,
memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
@ -431,15 +426,13 @@ impl VirtioPciDevice {
))
})?;
let msix_state =
vm_migration::versioned_state_from_id(snapshot.as_ref(), pci::MSIX_CONFIG_ID).map_err(
|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
"Failed to get MsixConfigState from Snapshot: {}",
e
))
},
)?;
let msix_state = vm_migration::state_from_id(snapshot.as_ref(), pci::MSIX_CONFIG_ID)
.map_err(|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
"Failed to get MsixConfigState from Snapshot: {}",
e
))
})?;
let (msix_config, msix_config_clone) = if msix_num > 0 {
let msix_config = Arc::new(Mutex::new(
@ -473,13 +466,14 @@ impl VirtioPciDevice {
};
let pci_configuration_state =
vm_migration::versioned_state_from_id(snapshot.as_ref(), pci::PCI_CONFIGURATION_ID)
.map_err(|e| {
vm_migration::state_from_id(snapshot.as_ref(), pci::PCI_CONFIGURATION_ID).map_err(
|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
"Failed to get PciConfigurationState from Snapshot: {}",
e
))
})?;
},
)?;
let configuration = PciConfiguration::new(
VIRTIO_PCI_VENDOR_ID,
@ -496,13 +490,14 @@ impl VirtioPciDevice {
);
let common_config_state =
vm_migration::versioned_state_from_id(snapshot.as_ref(), VIRTIO_PCI_COMMON_CONFIG_ID)
.map_err(|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
"Failed to get VirtioPciCommonConfigState from Snapshot: {}",
e
))
})?;
vm_migration::state_from_id(snapshot.as_ref(), VIRTIO_PCI_COMMON_CONFIG_ID).map_err(
|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
"Failed to get VirtioPciCommonConfigState from Snapshot: {}",
e
))
},
)?;
let common_config = if let Some(common_config_state) = common_config_state {
VirtioPciCommonConfig::new(common_config_state, access_platform)
@ -523,7 +518,7 @@ impl VirtioPciDevice {
let state: Option<VirtioPciDeviceState> = snapshot
.as_ref()
.map(|s| s.to_versioned_state())
.map(|s| s.to_state())
.transpose()
.map_err(|e| {
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
@ -1289,7 +1284,7 @@ impl Snapshottable for VirtioPciDevice {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let mut virtio_pci_dev_snapshot = Snapshot::new_from_versioned_state(&self.state())?;
let mut virtio_pci_dev_snapshot = Snapshot::new_from_state(&self.state())?;
// Snapshot PciConfiguration
virtio_pci_dev_snapshot

View File

@ -9,6 +9,7 @@ use crate::{
VIRTIO_F_IOMMU_PLATFORM,
};
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
io, result,
@ -18,8 +19,6 @@ use std::{
},
};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vhost::{
vdpa::{VhostVdpa, VhostVdpaIovaRange},
vhost_kern::VhostKernFeatures,
@ -29,9 +28,7 @@ use vhost::{
use virtio_queue::{Descriptor, Queue, QueueT};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
use vmm_sys_util::eventfd::EventFd;
@ -95,7 +92,7 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct VdpaState {
pub avail_features: u64,
pub acked_features: u64,
@ -107,8 +104,6 @@ pub struct VdpaState {
pub backend_features: u64,
}
impl VersionMapped for VdpaState {}
pub struct Vdpa {
common: VirtioCommon,
id: String,
@ -489,7 +484,7 @@ impl Snapshottable for Vdpa {
)));
}
let snapshot = Snapshot::new_from_versioned_state(&self.state().map_err(|e| {
let snapshot = Snapshot::new_from_state(&self.state().map_err(|e| {
MigratableError::Snapshot(anyhow!("Error snapshotting vDPA device: {:?}", e))
})?)?;

View File

@ -11,13 +11,13 @@ use crate::{GuestMemoryMmap, GuestRegionMmap};
use crate::{VirtioInterrupt, VIRTIO_F_IOMMU_PLATFORM};
use block::VirtioBlockConfig;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::mem;
use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vhost::vhost_user::message::{
VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
VHOST_USER_CONFIG_OFFSET,
@ -32,13 +32,13 @@ use virtio_queue::Queue;
use vm_memory::{ByteValued, GuestMemoryAtomic};
use vm_migration::{
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
Transportable, VersionMapped,
Transportable,
};
use vmm_sys_util::eventfd::EventFd;
const DEFAULT_QUEUE_NUMBER: usize = 1;
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct State {
pub avail_features: u64,
pub acked_features: u64,
@ -47,8 +47,6 @@ pub struct State {
pub vu_num_queues: usize,
}
impl VersionMapped for State {}
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}

View File

@ -13,14 +13,14 @@ use crate::{
use crate::{GuestMemoryMmap, GuestRegionMmap, MmapRegion};
use libc::{c_void, off64_t, pread64, pwrite64};
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, Bytes};
use std::io;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vhost::vhost_user::message::{
VhostUserFSBackendMsg, VhostUserFSBackendMsgFlags, VhostUserProtocolFeatures,
VhostUserVirtioFeatures, VHOST_USER_FS_BACKEND_ENTRIES,
@ -34,14 +34,14 @@ use vm_memory::{
};
use vm_migration::{
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
Transportable, VersionMapped,
Transportable,
};
use vmm_sys_util::eventfd::EventFd;
const NUM_QUEUE_OFFSET: usize = 1;
const DEFAULT_QUEUE_NUMBER: usize = 2;
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct State {
pub avail_features: u64,
pub acked_features: u64,
@ -51,8 +51,6 @@ pub struct State {
pub backend_req_support: bool,
}
impl VersionMapped for State {}
struct BackendReqHandler {
cache_offset: GuestAddress,
cache_size: u64,
@ -272,9 +270,11 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
}
pub const VIRTIO_FS_TAG_LEN: usize = 36;
#[derive(Copy, Clone, Versionize)]
#[serde_as]
#[derive(Copy, Clone, Serialize, Deserialize)]
#[repr(C, packed)]
pub struct VirtioFsConfig {
#[serde_as(as = "Bytes")]
pub tag: [u8; VIRTIO_FS_TAG_LEN],
pub num_request_queues: u32,
}

View File

@ -8,12 +8,12 @@ use crate::{
VIRTIO_F_RING_INDIRECT_DESC, VIRTIO_F_VERSION_1,
};
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use std::io;
use std::ops::Deref;
use std::os::unix::io::AsRawFd;
use std::sync::{atomic::AtomicBool, Arc, Barrier, Mutex};
use thiserror::Error;
use versionize::Versionize;
use vhost::vhost_user::message::{
VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
};
@ -25,7 +25,7 @@ use vm_memory::{
mmap::MmapRegionError, Address, Error as MmapError, GuestAddressSpace, GuestMemory,
GuestMemoryAtomic,
};
use vm_migration::{protocol::MemoryRangeTable, MigratableError, Snapshot, VersionMapped};
use vm_migration::{protocol::MemoryRangeTable, MigratableError, Snapshot};
use vmm_sys_util::eventfd::EventFd;
use vu_common_ctrl::VhostUserHandle;
@ -430,11 +430,11 @@ impl VhostUserCommon {
}
}
pub fn snapshot<T>(&mut self, state: &T) -> std::result::Result<Snapshot, MigratableError>
pub fn snapshot<'a, T>(&mut self, state: &T) -> std::result::Result<Snapshot, MigratableError>
where
T: Versionize + VersionMapped,
T: Serialize + Deserialize<'a>,
{
let snapshot = Snapshot::new_from_versioned_state(state)?;
let snapshot = Snapshot::new_from_state(state)?;
if self.migration_started {
self.shutdown();

View File

@ -12,12 +12,11 @@ use crate::{
use crate::{GuestMemoryMmap, GuestRegionMmap};
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler};
use virtio_bindings::virtio_net::{
@ -31,13 +30,13 @@ use virtio_queue::{Queue, QueueT};
use vm_memory::{ByteValued, GuestMemoryAtomic};
use vm_migration::{
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
Transportable, VersionMapped,
Transportable,
};
use vmm_sys_util::eventfd::EventFd;
const DEFAULT_QUEUE_NUMBER: usize = 2;
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct State {
pub avail_features: u64,
pub acked_features: u64,
@ -46,8 +45,6 @@ pub struct State {
pub vu_num_queues: usize,
}
impl VersionMapped for State {}
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}

View File

@ -40,22 +40,19 @@ use crate::{
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::io;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use std::result;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, RwLock};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::Queue;
use virtio_queue::QueueOwnedT;
use virtio_queue::QueueT;
use vm_memory::GuestAddressSpace;
use vm_memory::GuestMemoryAtomic;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::AccessPlatform;
use vmm_sys_util::eventfd::EventFd;
@ -323,14 +320,12 @@ pub struct Vsock<B: VsockBackend> {
exit_evt: EventFd,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct VsockState {
pub avail_features: u64,
pub acked_features: u64,
}
impl VersionMapped for VsockState {}
impl<B> Vsock<B>
where
B: VsockBackend + Sync,
@ -519,7 +514,7 @@ where
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}
impl<B> Transportable for Vsock<B> where B: VsockBackend + Sync + 'static {}
@ -787,6 +782,7 @@ mod tests {
let mut epoll_helper =
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert_eq!(ctx.guest_rxvq.used.idx.get(), 0);
assert!(
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed"
@ -807,6 +803,7 @@ mod tests {
let mut epoll_helper =
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert_eq!(ctx.guest_evvq.used.idx.get(), 0);
assert!(
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed"

View File

@ -256,7 +256,6 @@ mod tests {
pub struct TestContext {
pub cid: u64,
pub mem: GuestMemoryMmap,
pub mem_size: usize,
pub device: Vsock<TestBackend>,
}
@ -267,7 +266,6 @@ mod tests {
Self {
cid: CID as u64,
mem: GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(),
mem_size: MEM_SIZE,
device: Vsock::new(
String::from("vsock"),
CID,

View File

@ -16,6 +16,7 @@ use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{self, Read};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
@ -24,11 +25,8 @@ use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex};
use std::time::Instant;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT};
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
@ -197,15 +195,13 @@ pub struct Watchdog {
exit_evt: EventFd,
}
#[derive(Versionize)]
#[derive(Serialize, Deserialize)]
pub struct WatchdogState {
pub avail_features: u64,
pub acked_features: u64,
pub enabled: bool,
}
impl VersionMapped for WatchdogState {}
impl Watchdog {
/// Create a new virtio watchdog device that will reboot VM if the guest hangs
pub fn new(
@ -420,7 +416,7 @@ impl Snapshottable for Watchdog {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_versioned_state(&self.state())
Snapshot::new_from_state(&self.state())
}
}

View File

@ -219,10 +219,7 @@ mod tests {
#[test]
fn new_fails_overflow() {
assert_eq!(
AddressAllocator::new(GuestAddress(u64::max_value()), 0x100),
None
);
assert_eq!(AddressAllocator::new(GuestAddress(u64::MAX), 0x100), None);
}
#[test]

View File

@ -12,7 +12,7 @@ mshv = ["vfio-ioctls/mshv"]
[dependencies]
anyhow = "1.0.81"
hypervisor = { path = "../hypervisor" }
thiserror = "1.0.58"
thiserror = "1.0.60"
serde = { version = "1.0.197", features = ["rc", "derive"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.14.1", features = ["backend-mmap"] }

View File

@ -6,9 +6,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.81"
thiserror = "1.0.58"
thiserror = "1.0.60"
serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
versionize = "0.2.0"
versionize_derive = "0.1.6"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }

View File

@ -7,21 +7,9 @@ use crate::protocol::MemoryRangeTable;
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use versionize::{VersionMap, Versionize};
pub mod protocol;
/// Global VMM version for versioning
const MAJOR_VERSION: u16 = 38;
const MINOR_VERSION: u16 = 0;
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;
pub trait VersionMapped {
fn version_map() -> VersionMap {
VersionMap::new()
}
}
#[derive(Error, Debug)]
pub enum MigratableError {
#[error("Failed to pause migratable component: {0}")]
@ -80,7 +68,9 @@ pub trait Pausable {
/// Splitting a component migration data into different sections
/// allows for easier and forward compatible extensions.
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct SnapshotData(pub Vec<u8>);
pub struct SnapshotData {
state: String,
}
impl SnapshotData {
/// Generate the state data from the snapshot data
@ -88,16 +78,7 @@ impl SnapshotData {
where
T: Deserialize<'a>,
{
serde_json::from_slice(&self.0)
.map_err(|e| MigratableError::Restore(anyhow!("Error deserialising: {}", e)))
}
/// Generate versioned state
pub fn to_versioned_state<T>(&self) -> Result<T, MigratableError>
where
T: Versionize + VersionMapped,
{
T::deserialize(&mut self.0.as_slice(), &T::version_map(), VMM_VERSION)
serde_json::from_str(&self.state)
.map_err(|e| MigratableError::Restore(anyhow!("Error deserialising: {}", e)))
}
@ -106,23 +87,10 @@ impl SnapshotData {
where
T: Serialize,
{
let data = serde_json::to_vec(state)
let state = serde_json::to_string(state)
.map_err(|e| MigratableError::Snapshot(anyhow!("Error serialising: {}", e)))?;
Ok(SnapshotData(data))
}
/// Create from versioned state
pub fn new_from_versioned_state<T>(state: &T) -> Result<Self, MigratableError>
where
T: Versionize + VersionMapped,
{
let mut data = Vec::new();
state
.serialize(&mut data, &T::version_map(), VMM_VERSION)
.map_err(|e| MigratableError::Snapshot(anyhow!("Error serialising: {}", e)))?;
Ok(SnapshotData(data))
Ok(SnapshotData { state })
}
}
@ -163,16 +131,6 @@ impl Snapshot {
Ok(Snapshot::from_data(SnapshotData::new_from_state(state)?))
}
/// Create from versioned state
pub fn new_from_versioned_state<T>(state: &T) -> Result<Self, MigratableError>
where
T: Versionize + VersionMapped,
{
Ok(Snapshot::from_data(SnapshotData::new_from_versioned_state(
state,
)?))
}
/// Add a sub-component's Snapshot to the Snapshot.
pub fn add_snapshot(&mut self, id: String, snapshot: Snapshot) {
self.snapshots.insert(id, snapshot);
@ -188,34 +146,21 @@ impl Snapshot {
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing snapshot data")))?
.to_state()
}
/// Generate versioned state
pub fn to_versioned_state<T>(&self) -> Result<T, MigratableError>
where
T: Versionize + VersionMapped,
{
self.snapshot_data
.as_ref()
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing snapshot data")))?
.to_versioned_state()
}
}
pub fn snapshot_from_id(snapshot: Option<&Snapshot>, id: &str) -> Option<Snapshot> {
snapshot.and_then(|s| s.snapshots.get(id).cloned())
}
pub fn versioned_state_from_id<T>(
snapshot: Option<&Snapshot>,
id: &str,
) -> Result<Option<T>, MigratableError>
pub fn state_from_id<'a, T>(s: Option<&'a Snapshot>, id: &str) -> Result<Option<T>, MigratableError>
where
T: Versionize + VersionMapped,
T: Deserialize<'a>,
{
snapshot
.and_then(|s| s.snapshots.get(id).cloned())
.map(|s| s.to_versioned_state())
.transpose()
if let Some(s) = s.as_ref() {
s.snapshots.get(id).map(|s| s.to_state()).transpose()
} else {
Ok(None)
}
}
/// A snapshottable component can be snapshotted.

View File

@ -3,11 +3,9 @@
// SPDX-License-Identifier: Apache-2.0
//
use crate::{MigratableError, VersionMapped};
use crate::MigratableError;
use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_memory::ByteValued;
// Migration protocol
@ -199,19 +197,17 @@ impl Response {
}
#[repr(C)]
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct MemoryRange {
pub gpa: u64,
pub length: u64,
}
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct MemoryRangeTable {
data: Vec<MemoryRange>,
}
impl VersionMapped for MemoryRangeTable {}
impl MemoryRangeTable {
pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self {
let mut table = MemoryRangeTable::default();

View File

@ -9,5 +9,5 @@ default = []
[dependencies]
log = "0.4.21"
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

View File

@ -7,12 +7,13 @@ edition = "2021"
[features]
default = []
dbus_api = ["blocking", "futures", "zbus"]
dhat-heap = ["dhat"] # For heap profiling
guest_debug = ["kvm", "gdbstub", "gdbstub_arch"]
igvm = ["hex", "igvm_parser", "igvm_defs", "mshv-bindings", "range_map_vec"]
igvm = ["hex", "dep:igvm", "igvm_defs", "mshv-bindings", "range_map_vec"]
io_uring = ["block/io_uring"]
kvm = ["hypervisor/kvm", "vfio-ioctls/kvm", "vm-device/kvm", "pci/kvm"]
mshv = ["hypervisor/mshv", "vfio-ioctls/mshv", "vm-device/mshv", "pci/mshv"]
sev_snp = ["arch/sev_snp", "hypervisor/sev_snp"]
sev_snp = ["arch/sev_snp", "hypervisor/sev_snp", "virtio-devices/sev_snp"]
tdx = ["arch/tdx", "hypervisor/tdx"]
tracing = ["tracer/tracing"]
@ -27,6 +28,7 @@ blocking = { version = "1.5.1", optional = true }
cfg-if = "1.0.0"
clap = "4.5.4"
devices = { path = "../devices" }
dhat = { version = "0.3.3", optional = true }
epoll = "4.3.3"
event_monitor = { path = "../event_monitor" }
flume = "0.11.0"
@ -35,8 +37,8 @@ gdbstub = { version = "0.7.1", optional = true }
gdbstub_arch = { version = "0.3.0", optional = true }
hex = { version = "0.4.3", optional = true }
hypervisor = { path = "../hypervisor" }
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
igvm = { version = "0.2.0", optional = true }
igvm_defs = { version = "0.2.0", optional = true }
libc = "0.2.153"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.21"
@ -53,15 +55,13 @@ serde = { version = "1.0.197", features = ["rc", "derive"] }
serde_json = "1.0.115"
serial_buffer = { path = "../serial_buffer" }
signal-hook = "0.3.17"
thiserror = "1.0.58"
thiserror = "1.0.60"
tracer = { path = "../tracer" }
uuid = "1.8.0"
versionize = "0.2.0"
versionize_derive = "0.1.6"
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" }
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.11.0"
virtio-queue = "0.12.0"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

8
vmm/build.rs Normal file
View File

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

View File

@ -618,6 +618,10 @@ components:
pvpanic:
type: boolean
default: false
pci_segments:
type: array
items:
$ref: "#/components/schemas/PciSegmentConfig"
platform:
$ref: "#/components/schemas/PlatformConfig"
tpm:
@ -663,11 +667,9 @@ components:
properties:
boot_vcpus:
minimum: 1
default: 1
type: integer
max_vcpus:
minimum: 1
default: 1
type: integer
topology:
$ref: "#/components/schemas/CpuTopology"
@ -683,6 +685,21 @@ components:
features:
$ref: "#/components/schemas/CpuFeatures"
PciSegmentConfig:
required:
- pci_segment
type: object
properties:
pci_segment:
type: integer
format: int16
mmio32_aperture_weight:
type: integer
format: int32
mmio64_aperture_weight:
type: integer
format: int32
PlatformConfig:
type: object
properties:
@ -717,7 +734,6 @@ components:
size:
type: integer
format: int64
default: 512 MB
file:
type: string
mergeable:
@ -753,7 +769,6 @@ components:
size:
type: integer
format: int64
default: 512 MB
hotplug_size:
type: integer
format: int64
@ -838,7 +853,7 @@ components:
type: string
rate_limiter_config:
$ref: "#/components/schemas/RateLimiterConfig"
VirtQueueAffinity:
required:
- queue_index
@ -944,7 +959,6 @@ components:
properties:
src:
type: string
default: "/dev/urandom"
iommu:
type: boolean
default: false

View File

@ -98,6 +98,8 @@ pub enum Error {
ParseUserDevice(OptionParserError),
/// Missing socket for userspace device
ParseUserDeviceSocketMissing,
/// Error parsing pci segment options
ParsePciSegment(OptionParserError),
/// Failed parsing platform parameters
ParsePlatform(OptionParserError),
/// Failed parsing vDPA device
@ -170,6 +172,8 @@ pub enum ValidationError {
InvalidNumPciSegments(u16),
/// Invalid PCI segment id
InvalidPciSegment(u16),
/// Invalid PCI segment aperture weight
InvalidPciSegmentApertureWeight(u32),
/// Balloon too big
BalloonLargerThanRam(u64, u64),
/// On a IOMMU segment but not behind IOMMU
@ -279,6 +283,9 @@ impl fmt::Display for ValidationError {
InvalidPciSegment(pci_segment) => {
write!(f, "Invalid PCI segment id: {pci_segment}")
}
InvalidPciSegmentApertureWeight(aperture_weight) => {
write!(f, "Invalid PCI segment aperture weight: {aperture_weight}")
}
BalloonLargerThanRam(balloon_size, ram_size) => {
write!(
f,
@ -395,6 +402,7 @@ impl fmt::Display for Error {
ParseTdx(o) => write!(f, "Error parsing --tdx: {o}"),
#[cfg(feature = "tdx")]
FirmwarePathMissing => write!(f, "TDX firmware missing"),
ParsePciSegment(o) => write!(f, "Error parsing --pci-segment: {o}"),
ParsePlatform(o) => write!(f, "Error parsing --platform: {o}"),
ParseVdpa(o) => write!(f, "Error parsing --vdpa: {o}"),
ParseVdpaPathMissing => write!(f, "Error parsing --vdpa: path missing"),
@ -444,6 +452,7 @@ pub struct VmParams<'a> {
pub watchdog: bool,
#[cfg(feature = "guest_debug")]
pub gdb: bool,
pub pci_segments: Option<Vec<&'a str>>,
pub platform: Option<&'a str>,
pub tpm: Option<&'a str>,
#[cfg(feature = "igvm")]
@ -504,6 +513,9 @@ impl<'a> VmParams<'a> {
.get_many::<String>("numa")
.map(|x| x.map(|y| y as &str).collect());
let watchdog = args.get_flag("watchdog");
let pci_segments: Option<Vec<&str>> = args
.get_many::<String>("pci-segment")
.map(|x| x.map(|y| y as &str).collect());
let platform = args.get_one::<String>("platform").map(|x| x as &str);
#[cfg(feature = "guest_debug")]
let gdb = args.contains_id("gdb");
@ -542,6 +554,7 @@ impl<'a> VmParams<'a> {
watchdog,
#[cfg(feature = "guest_debug")]
gdb,
pci_segments,
platform,
tpm,
#[cfg(feature = "igvm")]
@ -678,6 +691,64 @@ impl CpusConfig {
}
}
impl PciSegmentConfig {
pub const SYNTAX: &'static str = "PCI Segment parameters \
\"pci_segment=<segment_id>,mmio32_aperture_weight=<scale>,mmio64_aperture_weight=<scale>\"";
pub fn parse(disk: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
.add("mmio32_aperture_weight")
.add("mmio64_aperture_weight")
.add("pci_segment");
parser.parse(disk).map_err(Error::ParsePciSegment)?;
let pci_segment = parser
.convert("pci_segment")
.map_err(Error::ParsePciSegment)?
.unwrap_or_default();
let mmio32_aperture_weight = parser
.convert("mmio32_aperture_weight")
.map_err(Error::ParsePciSegment)?
.unwrap_or(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT);
let mmio64_aperture_weight = parser
.convert("mmio64_aperture_weight")
.map_err(Error::ParsePciSegment)?
.unwrap_or(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT);
Ok(PciSegmentConfig {
pci_segment,
mmio32_aperture_weight,
mmio64_aperture_weight,
})
}
pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> {
let num_pci_segments = match &vm_config.platform {
Some(platform_config) => platform_config.num_pci_segments,
None => 1,
};
if self.pci_segment >= num_pci_segments {
return Err(ValidationError::InvalidPciSegment(self.pci_segment));
}
if self.mmio32_aperture_weight == 0 {
return Err(ValidationError::InvalidPciSegmentApertureWeight(
self.mmio32_aperture_weight,
));
}
if self.mmio64_aperture_weight == 0 {
return Err(ValidationError::InvalidPciSegmentApertureWeight(
self.mmio64_aperture_weight,
));
}
Ok(())
}
}
impl PlatformConfig {
pub fn parse(platform: &str) -> Result<Self> {
let mut parser = OptionParser::new();
@ -2449,6 +2520,12 @@ impl VmConfig {
}
}
if let Some(pci_segments) = &self.pci_segments {
for pci_segment in pci_segments {
pci_segment.validate(self)?;
}
}
self.platform.as_ref().map(|p| p.validate()).transpose()?;
self.iommu |= self
.platform
@ -2557,6 +2634,16 @@ impl VmConfig {
vsock = Some(vsock_config);
}
let mut pci_segments: Option<Vec<PciSegmentConfig>> = None;
if let Some(pci_segment_list) = &vm_params.pci_segments {
let mut pci_segment_config_list = Vec::new();
for item in pci_segment_list.iter() {
let pci_segment_config = PciSegmentConfig::parse(item)?;
pci_segment_config_list.push(pci_segment_config);
}
pci_segments = Some(pci_segment_config_list);
}
let platform = vm_params.platform.map(PlatformConfig::parse).transpose()?;
#[cfg(target_arch = "x86_64")]
@ -2643,6 +2730,7 @@ impl VmConfig {
watchdog: vm_params.watchdog,
#[cfg(feature = "guest_debug")]
gdb,
pci_segments,
platform,
tpm,
preserved_fds: None,
@ -2764,6 +2852,7 @@ impl Clone for VmConfig {
#[cfg(target_arch = "x86_64")]
sgx_epc: self.sgx_epc.clone(),
numa: self.numa.clone(),
pci_segments: self.pci_segments.clone(),
platform: self.platform.clone(),
tpm: self.tpm.clone(),
preserved_fds: self
@ -2960,6 +3049,46 @@ mod tests {
Ok(())
}
#[test]
fn test_pci_segment_parsing() -> Result<()> {
assert_eq!(
PciSegmentConfig::parse("pci_segment=0")?,
PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 1,
mmio64_aperture_weight: 1,
}
);
assert_eq!(
PciSegmentConfig::parse(
"pci_segment=0,mmio32_aperture_weight=1,mmio64_aperture_weight=1"
)?,
PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 1,
mmio64_aperture_weight: 1,
}
);
assert_eq!(
PciSegmentConfig::parse("pci_segment=0,mmio32_aperture_weight=2")?,
PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 2,
mmio64_aperture_weight: 1,
}
);
assert_eq!(
PciSegmentConfig::parse("pci_segment=0,mmio64_aperture_weight=2")?,
PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 1,
mmio64_aperture_weight: 2,
}
);
Ok(())
}
fn disk_fixture() -> DiskConfig {
DiskConfig {
path: Some(PathBuf::from("/path/to_file")),
@ -3536,6 +3665,7 @@ mod tests {
watchdog: false,
#[cfg(feature = "guest_debug")]
gdb: false,
pci_segments: None,
platform: None,
tpm: None,
preserved_fds: None,
@ -3946,6 +4076,28 @@ mod tests {
Err(ValidationError::PciSegmentReused(1, 0, 1))
);
let mut invalid_config = valid_config.clone();
invalid_config.pci_segments = Some(vec![PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 1,
mmio64_aperture_weight: 0,
}]);
assert_eq!(
invalid_config.validate(),
Err(ValidationError::InvalidPciSegmentApertureWeight(0))
);
let mut invalid_config = valid_config.clone();
invalid_config.pci_segments = Some(vec![PciSegmentConfig {
pci_segment: 0,
mmio32_aperture_weight: 0,
mmio64_aperture_weight: 1,
}]);
assert_eq!(
invalid_config.validate(),
Err(ValidationError::InvalidPciSegmentApertureWeight(0))
);
let mut invalid_config = valid_config.clone();
invalid_config.numa = Some(vec![
NumaConfig {

259
vmm/src/console_devices.rs Normal file
View File

@ -0,0 +1,259 @@
use crate::sigwinch_listener::listen_for_sigwinch_on_tty;
use crate::vm_config::ConsoleOutputMode;
use crate::Vmm;
use libc::cfmakeraw;
use libc::isatty;
use libc::tcgetattr;
use libc::tcsetattr;
use libc::termios;
use libc::TCSANOW;
use std::fs::read_link;
use std::fs::File;
use std::fs::OpenOptions;
use std::io;
use std::io::stdout;
use std::mem::zeroed;
use std::os::fd::AsRawFd;
use std::os::fd::FromRawFd;
use std::os::fd::IntoRawFd;
use std::os::fd::RawFd;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::net::UnixListener;
use std::path::PathBuf;
use std::result;
use std::sync::Arc;
use std::sync::Mutex;
/// Errors associated with console devices
#[derive(Debug)]
pub enum ConsoleDeviceError {
/// Error creating console device
CreateConsoleDevice(io::Error),
/// Error setting pty raw mode
SetPtyRaw(vmm_sys_util::errno::Error),
/// Cannot duplicate file descriptor
DupFd(vmm_sys_util::errno::Error),
/// Error starting sigwinch listener
StartSigwinchListener(std::io::Error),
}
pub type ConsoleDeviceResult<T> = result::Result<T, ConsoleDeviceError>;
#[derive(Default, Clone)]
pub struct ConsoleInfo {
// For each of File, Pty, Tty, Socket modes, xxxx_main_fd will hold the FD
// of the opened path.
pub console_main_fd: Option<RawFd>,
pub serial_main_fd: Option<RawFd>,
#[cfg(target_arch = "x86_64")]
pub debug_main_fd: Option<RawFd>,
}
fn modify_mode<F: FnOnce(&mut termios)>(
fd: RawFd,
f: F,
original_termios_opt: Arc<Mutex<Option<termios>>>,
) -> vmm_sys_util::errno::Result<()> {
// SAFETY: safe because we check the return value of isatty.
if unsafe { isatty(fd) } != 1 {
return Ok(());
}
// SAFETY: The following pair are safe because termios gets totally overwritten by tcgetattr
// and we check the return result.
let mut termios: termios = unsafe { zeroed() };
// SAFETY: see above
let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) };
if ret < 0 {
return vmm_sys_util::errno::errno_result();
}
let mut original_termios_opt = original_termios_opt.lock().unwrap();
if original_termios_opt.is_none() {
original_termios_opt.replace(termios);
}
f(&mut termios);
// SAFETY: Safe because the syscall will only read the extent of termios and we check
// the return result.
let ret = unsafe { tcsetattr(fd, TCSANOW, &termios as *const _) };
if ret < 0 {
return vmm_sys_util::errno::errno_result();
}
Ok(())
}
pub fn set_raw_mode(
f: &dyn AsRawFd,
original_termios_opt: Arc<Mutex<Option<termios>>>,
) -> ConsoleDeviceResult<()> {
// SAFETY: FFI call. Variable t is guaranteed to be a valid termios from modify_mode.
modify_mode(
f.as_raw_fd(),
|t| unsafe { cfmakeraw(t) },
original_termios_opt,
)
.map_err(ConsoleDeviceError::SetPtyRaw)
}
const TIOCSPTLCK: libc::c_int = 0x4004_5431;
const TIOCGTPEER: libc::c_int = 0x5441;
pub fn create_pty() -> io::Result<(File, File, PathBuf)> {
// Try to use /dev/pts/ptmx first then fall back to /dev/ptmx
// This is done to try and use the devpts filesystem that
// could be available for use in the process's namespace first.
// Ideally these are all the same file though but different
// kernels could have things setup differently.
// See https://www.kernel.org/doc/Documentation/filesystems/devpts.txt
// for further details.
let custom_flags = libc::O_NONBLOCK;
let main = match OpenOptions::new()
.read(true)
.write(true)
.custom_flags(custom_flags)
.open("/dev/pts/ptmx")
{
Ok(f) => f,
_ => OpenOptions::new()
.read(true)
.write(true)
.custom_flags(custom_flags)
.open("/dev/ptmx")?,
};
let mut unlock: libc::c_ulong = 0;
// SAFETY: FFI call into libc, trivially safe
unsafe { libc::ioctl(main.as_raw_fd(), TIOCSPTLCK as _, &mut unlock) };
// SAFETY: FFI call into libc, trivially safe
let sub_fd = unsafe {
libc::ioctl(
main.as_raw_fd(),
TIOCGTPEER as _,
libc::O_NOCTTY | libc::O_RDWR,
)
};
if sub_fd == -1 {
return vmm_sys_util::errno::errno_result().map_err(|e| e.into());
}
let proc_path = PathBuf::from(format!("/proc/self/fd/{sub_fd}"));
let path = read_link(proc_path)?;
// SAFETY: sub_fd is checked to be valid before being wrapped in File
Ok((main, unsafe { File::from_raw_fd(sub_fd) }, path))
}
pub fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<ConsoleInfo> {
let vm_config = vmm.vm_config.as_mut().unwrap().clone();
let mut vmconfig = vm_config.lock().unwrap();
let mut console_info = ConsoleInfo::default();
match vmconfig.console.mode {
ConsoleOutputMode::File => {
let file = File::create(vmconfig.console.file.as_ref().unwrap())
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.console_main_fd = Some(file.into_raw_fd());
}
ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.console_main_fd = Some(main_fd.into_raw_fd());
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
vmconfig.console.file = Some(path.clone());
vmm.console_resize_pipe = Some(
listen_for_sigwinch_on_tty(
sub_fd,
&vmm.seccomp_action,
vmm.hypervisor.hypervisor_type(),
)
.map_err(ConsoleDeviceError::StartSigwinchListener)?,
);
}
ConsoleOutputMode::Tty => {
// Duplicating the file descriptors like this is needed as otherwise
// they will be closed on a reboot and the numbers reused
// SAFETY: FFI call to dup. Trivially safe.
let stdout = unsafe { libc::dup(libc::STDOUT_FILENO) };
if stdout == -1 {
return vmm_sys_util::errno::errno_result().map_err(ConsoleDeviceError::DupFd);
}
// SAFETY: stdout is valid and owned solely by us.
let stdout = unsafe { File::from_raw_fd(stdout) };
// SAFETY: FFI call. Trivially safe.
if unsafe { libc::isatty(libc::STDOUT_FILENO) } == 1 {
vmm.console_resize_pipe = Some(
listen_for_sigwinch_on_tty(
stdout.try_clone().unwrap(),
&vmm.seccomp_action,
vmm.hypervisor.hypervisor_type(),
)
.map_err(ConsoleDeviceError::StartSigwinchListener)?,
);
}
// Make sure stdout is in raw mode, if it's a terminal.
set_raw_mode(&stdout, vmm.original_termios_opt.clone())?;
console_info.console_main_fd = Some(stdout.into_raw_fd());
}
ConsoleOutputMode::Null | ConsoleOutputMode::Socket | ConsoleOutputMode::Off => {}
}
match vmconfig.serial.mode {
ConsoleOutputMode::File => {
let file = File::create(vmconfig.serial.file.as_ref().unwrap())
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.serial_main_fd = Some(file.into_raw_fd());
}
ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.serial_main_fd = Some(main_fd.into_raw_fd());
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
vmconfig.serial.file = Some(path.clone());
}
ConsoleOutputMode::Tty => {
let out = stdout();
console_info.serial_main_fd = Some(out.as_raw_fd());
set_raw_mode(&out, vmm.original_termios_opt.clone())?;
}
ConsoleOutputMode::Socket => {
let listener = UnixListener::bind(vmconfig.serial.socket.as_ref().unwrap())
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.serial_main_fd = Some(listener.into_raw_fd());
}
ConsoleOutputMode::Null | ConsoleOutputMode::Off => {}
}
#[cfg(target_arch = "x86_64")]
match vmconfig.debug_console.mode {
ConsoleOutputMode::File => {
let file = File::create(vmconfig.debug_console.file.as_ref().unwrap())
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.debug_main_fd = Some(file.into_raw_fd());
}
ConsoleOutputMode::Pty => {
let (main_fd, sub_fd, path) =
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
console_info.debug_main_fd = Some(main_fd.into_raw_fd());
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
vmconfig.debug_console.file = Some(path.clone());
}
ConsoleOutputMode::Tty => {
let out = stdout();
console_info.debug_main_fd = Some(out.as_raw_fd());
set_raw_mode(&out, vmm.original_termios_opt.clone())?;
}
ConsoleOutputMode::Null | ConsoleOutputMode::Socket | ConsoleOutputMode::Off => {}
}
Ok(console_info)
}

View File

@ -1147,15 +1147,6 @@ impl CpuManager {
unreachable!("Couldn't get a mutable reference from Arc<dyn Vcpu> as there are multiple instances");
}
}
_ => {
error!(
"VCPU generated error: {:?}",
Error::UnexpectedVmExit
);
vcpu_run_interrupted.store(true, Ordering::SeqCst);
exit_evt.write(1).unwrap();
break;
}
},
Err(e) => {

View File

@ -13,15 +13,16 @@ use crate::config::{
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig,
VdpaConfig, VhostMode, VmConfig, VsockConfig,
};
use crate::console_devices::ConsoleDeviceError;
use crate::console_devices::ConsoleInfo;
use crate::cpu::{CpuManager, CPU_MANAGER_ACPI_SIZE};
use crate::device_tree::{DeviceNode, DeviceTree};
use crate::interrupt::LegacyUserspaceInterruptManager;
use crate::interrupt::MsiInterruptManager;
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager, MEMORY_MANAGER_ACPI_SIZE};
use crate::pci_segment::PciSegment;
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use crate::serial_manager::{Error as SerialManagerError, SerialManager};
use crate::sigwinch_listener::start_sigwinch_listener;
use crate::vm_config::DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT;
use crate::GuestRegionMmap;
use crate::PciDeviceInfo;
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
@ -52,10 +53,10 @@ use devices::legacy::Pl011;
use devices::{
interrupt_controller, interrupt_controller::InterruptController, AcpiNotificationFlags,
};
use hypervisor::{HypervisorType, IoEventAddress};
use hypervisor::IoEventAddress;
use libc::{
cfmakeraw, isatty, tcgetattr, tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED,
O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW,
tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE,
TCSANOW,
};
use pci::{
DeviceRelocation, MmioRegion, PciBarRegionType, PciBdf, PciDevice, VfioDmaMapping,
@ -67,10 +68,10 @@ use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fs::{read_link, File, OpenOptions};
use std::io::{self, stdout, Seek, SeekFrom};
use std::mem::zeroed;
use std::num::Wrapping;
use std::os::fd::RawFd;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::PathBuf;
use std::result;
use std::sync::{Arc, Mutex};
@ -96,8 +97,8 @@ use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion};
#[cfg(target_arch = "x86_64")]
use vm_memory::{GuestAddressSpace, GuestMemory};
use vm_migration::{
protocol::MemoryRangeTable, snapshot_from_id, versioned_state_from_id, Migratable,
MigratableError, Pausable, Snapshot, SnapshotData, Snapshottable, Transportable,
protocol::MemoryRangeTable, snapshot_from_id, state_from_id, Migratable, MigratableError,
Pausable, Snapshot, SnapshotData, Snapshottable, Transportable,
};
use vm_virtio::AccessPlatform;
use vm_virtio::VirtioDeviceType;
@ -269,7 +270,7 @@ pub enum DeviceManagerError {
DebugconPtyOpen(io::Error),
/// Error setting pty raw mode
SetPtyRaw(vmm_sys_util::errno::Error),
SetPtyRaw(ConsoleDeviceError),
/// Error getting pty peer
GetPtyPeer(vmm_sys_util::errno::Error),
@ -493,6 +494,15 @@ pub enum DeviceManagerError {
/// Cannot create a RateLimiterGroup
RateLimiterGroupCreate(rate_limiter::group::Error),
/// Cannot start sigwinch listener
StartSigwinchListener(std::io::Error),
// Invalid console info
InvalidConsoleInfo,
// Invalid console fd
InvalidConsoleFd,
}
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
@ -814,24 +824,12 @@ pub struct AcpiPlatformAddresses {
}
pub struct DeviceManager {
// The underlying hypervisor
hypervisor_type: HypervisorType,
// Manage address space related to devices
address_manager: Arc<AddressManager>,
// Console abstraction
console: Arc<Console>,
// console PTY
console_pty: Option<Arc<Mutex<PtyPair>>>,
// serial PTY
serial_pty: Option<Arc<Mutex<PtyPair>>>,
// debug-console PTY
debug_console_pty: Option<Arc<Mutex<PtyPair>>>,
// Serial Manager
serial_manager: Option<Arc<SerialManager>>,
@ -969,12 +967,39 @@ pub struct DeviceManager {
mmio_regions: Arc<Mutex<Vec<MmioRegion>>>,
}
fn create_mmio_allocators(
start: u64,
end: u64,
num_pci_segments: u16,
weights: Vec<u32>,
alignment: u64,
) -> Vec<Arc<Mutex<AddressAllocator>>> {
let total_weight: u32 = weights.iter().sum();
// Start each PCI segment mmio range on an aligned boundary
let pci_segment_mmio_size = (end - start + 1) / (alignment * total_weight as u64) * alignment;
let mut mmio_allocators = vec![];
let mut i = 0;
for segment_id in 0..num_pci_segments as u64 {
let weight = weights[segment_id as usize] as u64;
let mmio_start = start + i * pci_segment_mmio_size;
let mmio_size = pci_segment_mmio_size * weight;
let allocator = Arc::new(Mutex::new(
AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(),
));
mmio_allocators.push(allocator);
i += weight;
}
mmio_allocators
}
impl DeviceManager {
#[allow(clippy::too_many_arguments)]
pub fn new(
#[cfg(target_arch = "x86_64")] io_bus: Arc<Bus>,
mmio_bus: Arc<Bus>,
hypervisor_type: HypervisorType,
vm: Arc<dyn hypervisor::Vm>,
config: Arc<Mutex<VmConfig>>,
memory_manager: Arc<Mutex<MemoryManager>>,
@ -1009,22 +1034,16 @@ impl DeviceManager {
1
};
let create_mmio_allocators = |start, end, num_pci_segments, alignment| {
// Start each PCI segment mmio range on an aligned boundary
let pci_segment_mmio_size =
(end - start + 1) / (alignment * num_pci_segments as u64) * alignment;
let mut mmio_allocators = vec![];
for i in 0..num_pci_segments as u64 {
let mmio_start = start + i * pci_segment_mmio_size;
let allocator = Arc::new(Mutex::new(
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_mmio_size).unwrap(),
));
mmio_allocators.push(allocator)
let mut mmio32_aperture_weights: Vec<u32> =
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
.take(num_pci_segments.into())
.collect();
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
for pci_segment in pci_segments.iter() {
mmio32_aperture_weights[pci_segment.pci_segment as usize] =
pci_segment.mmio32_aperture_weight
}
mmio_allocators
};
}
let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
@ -1032,15 +1051,28 @@ impl DeviceManager {
start_of_mmio32_area,
end_of_mmio32_area,
num_pci_segments,
mmio32_aperture_weights,
4 << 10,
);
let mut mmio64_aperture_weights: Vec<u32> =
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
.take(num_pci_segments.into())
.collect();
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
for pci_segment in pci_segments.iter() {
mmio64_aperture_weights[pci_segment.pci_segment as usize] =
pci_segment.mmio64_aperture_weight
}
}
let start_of_mmio64_area = memory_manager.lock().unwrap().start_of_device_area().0;
let end_of_mmio64_area = memory_manager.lock().unwrap().end_of_device_area().0;
let pci_mmio64_allocators = create_mmio_allocators(
start_of_mmio64_area,
end_of_mmio64_area,
num_pci_segments,
mmio64_aperture_weights,
4 << 30,
);
@ -1144,7 +1176,6 @@ impl DeviceManager {
}
let device_manager = DeviceManager {
hypervisor_type,
address_manager: Arc::clone(&address_manager),
console: Arc::new(Console::default()),
interrupt_controller: None,
@ -1178,10 +1209,7 @@ impl DeviceManager {
.map_err(DeviceManagerError::EventFd)?,
acpi_address,
selected_segment: 0,
serial_pty: None,
serial_manager: None,
console_pty: None,
debug_console_pty: None,
console_resize_pipe: None,
original_termios_opt: Arc::new(Mutex::new(None)),
virtio_mem_devices: Vec::new(),
@ -1214,33 +1242,13 @@ impl DeviceManager {
Ok(device_manager)
}
pub fn serial_pty(&self) -> Option<PtyPair> {
self.serial_pty
.as_ref()
.map(|pty| pty.lock().unwrap().clone())
}
pub fn console_pty(&self) -> Option<PtyPair> {
self.console_pty
.as_ref()
.map(|pty| pty.lock().unwrap().clone())
}
pub fn debug_console_pty(&self) -> Option<PtyPair> {
self.debug_console_pty
.as_ref()
.map(|pty| pty.lock().unwrap().clone())
}
pub fn console_resize_pipe(&self) -> Option<Arc<File>> {
self.console_resize_pipe.clone()
}
pub fn create_devices(
&mut self,
serial_pty: Option<PtyPair>,
console_pty: Option<PtyPair>,
debug_console_pty: Option<PtyPair>,
console_info: Option<ConsoleInfo>,
console_resize_pipe: Option<File>,
original_termios_opt: Arc<Mutex<Option<termios>>>,
) -> DeviceManagerResult<()> {
@ -1303,9 +1311,7 @@ impl DeviceManager {
self.console = self.add_console_devices(
&legacy_interrupt_manager,
&mut virtio_devices,
serial_pty,
console_pty,
debug_console_pty,
console_info,
console_resize_pipe,
)?;
@ -1371,7 +1377,7 @@ impl DeviceManager {
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.get_msi_iova_space(),
versioned_state_from_id(self.snapshot.as_ref(), iommu_id.as_str())
state_from_id(self.snapshot.as_ref(), iommu_id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioIommu)?;
@ -1519,7 +1525,7 @@ impl DeviceManager {
id.clone(),
APIC_START,
Arc::clone(&self.msi_interrupt_manager),
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateInterruptController)?,
@ -1791,7 +1797,7 @@ impl DeviceManager {
let gpio_device = Arc::new(Mutex::new(devices::legacy::Gpio::new(
id.clone(),
interrupt_group,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)));
@ -1892,7 +1898,7 @@ impl DeviceManager {
id.clone(),
interrupt_group,
serial_writer,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)));
@ -1949,7 +1955,7 @@ impl DeviceManager {
interrupt_group,
serial_writer,
self.timestamp,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)));
@ -1986,127 +1992,50 @@ impl DeviceManager {
Ok(serial)
}
fn modify_mode<F: FnOnce(&mut termios)>(
&mut self,
fd: RawFd,
f: F,
) -> vmm_sys_util::errno::Result<()> {
// SAFETY: safe because we check the return value of isatty.
if unsafe { isatty(fd) } != 1 {
return Ok(());
}
// SAFETY: The following pair are safe because termios gets totally overwritten by tcgetattr
// and we check the return result.
let mut termios: termios = unsafe { zeroed() };
// SAFETY: see above
let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) };
if ret < 0 {
return vmm_sys_util::errno::errno_result();
}
let mut original_termios_opt = self.original_termios_opt.lock().unwrap();
if original_termios_opt.is_none() {
*original_termios_opt = Some(termios);
}
f(&mut termios);
// SAFETY: Safe because the syscall will only read the extent of termios and we check
// the return result.
let ret = unsafe { tcsetattr(fd, TCSANOW, &termios as *const _) };
if ret < 0 {
return vmm_sys_util::errno::errno_result();
}
Ok(())
}
fn set_raw_mode(&mut self, f: &dyn AsRawFd) -> vmm_sys_util::errno::Result<()> {
// SAFETY: FFI call. Variable t is guaranteed to be a valid termios from modify_mode.
self.modify_mode(f.as_raw_fd(), |t| unsafe { cfmakeraw(t) })
}
fn listen_for_sigwinch_on_tty(&mut self, pty_sub: File) -> std::io::Result<()> {
let seccomp_filter = get_seccomp_filter(
&self.seccomp_action,
Thread::PtyForeground,
self.hypervisor_type,
)
.unwrap();
self.console_resize_pipe =
Some(Arc::new(start_sigwinch_listener(seccomp_filter, pty_sub)?));
Ok(())
}
fn add_virtio_console_device(
&mut self,
virtio_devices: &mut Vec<MetaVirtioDevice>,
console_pty: Option<PtyPair>,
console_fd: Option<RawFd>,
resize_pipe: Option<File>,
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
let console_config = self.config.lock().unwrap().console.clone();
let endpoint = match console_config.mode {
ConsoleOutputMode::File => {
let file = File::create(console_config.file.as_ref().unwrap())
.map_err(DeviceManagerError::ConsoleOutputFileOpen)?;
Endpoint::File(file)
if let Some(file_fd) = console_fd {
Endpoint::File(unsafe { File::from_raw_fd(file_fd) })
} else {
return Err(DeviceManagerError::InvalidConsoleFd);
}
}
ConsoleOutputMode::Pty => {
if let Some(pty) = console_pty {
self.config.lock().unwrap().console.file = Some(pty.path.clone());
let file = pty.main.try_clone().unwrap();
self.console_pty = Some(Arc::new(Mutex::new(pty)));
if let Some(pty_fd) = console_fd {
let file = unsafe { File::from_raw_fd(pty_fd) };
self.console_resize_pipe = resize_pipe.map(Arc::new);
Endpoint::PtyPair(file.try_clone().unwrap(), file)
} else {
let (main, sub, path) =
create_pty().map_err(DeviceManagerError::ConsolePtyOpen)?;
self.set_raw_mode(&sub)
.map_err(DeviceManagerError::SetPtyRaw)?;
self.config.lock().unwrap().console.file = Some(path.clone());
let file = main.try_clone().unwrap();
assert!(resize_pipe.is_none());
self.listen_for_sigwinch_on_tty(sub).unwrap();
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
Endpoint::PtyPair(file.try_clone().unwrap(), file)
return Err(DeviceManagerError::InvalidConsoleFd);
}
}
ConsoleOutputMode::Tty => {
// Duplicating the file descriptors like this is needed as otherwise
// they will be closed on a reboot and the numbers reused
// SAFETY: FFI call to dup. Trivially safe.
let stdout = unsafe { libc::dup(libc::STDOUT_FILENO) };
if stdout == -1 {
return vmm_sys_util::errno::errno_result().map_err(DeviceManagerError::DupFd);
}
// SAFETY: stdout is valid and owned solely by us.
let stdout = unsafe { File::from_raw_fd(stdout) };
// Make sure stdout is in raw mode, if it's a terminal.
let _ = self.set_raw_mode(&stdout);
// SAFETY: FFI call. Trivially safe.
if unsafe { libc::isatty(libc::STDOUT_FILENO) } == 1 {
self.listen_for_sigwinch_on_tty(stdout.try_clone().unwrap())
.unwrap();
}
// If an interactive TTY then we can accept input
// SAFETY: FFI call. Trivially safe.
if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
// SAFETY: FFI call to dup. Trivially safe.
let stdin = unsafe { libc::dup(libc::STDIN_FILENO) };
if stdin == -1 {
return vmm_sys_util::errno::errno_result()
.map_err(DeviceManagerError::DupFd);
if let Some(tty_fd) = console_fd {
let stdout = unsafe { File::from_raw_fd(tty_fd) };
// If an interactive TTY then we can accept input
// SAFETY: FFI call. Trivially safe.
if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
// SAFETY: FFI call to dup. Trivially safe.
let stdin = unsafe { libc::dup(libc::STDIN_FILENO) };
if stdin == -1 {
return vmm_sys_util::errno::errno_result()
.map_err(DeviceManagerError::DupFd);
}
// SAFETY: stdin is valid and owned solely by us.
let stdin = unsafe { File::from_raw_fd(stdin) };
Endpoint::FilePair(stdout, stdin)
} else {
Endpoint::File(stdout)
}
// SAFETY: stdin is valid and owned solely by us.
let stdin = unsafe { File::from_raw_fd(stdin) };
Endpoint::FilePair(stdout, stdin)
} else {
Endpoint::File(stdout)
return Err(DeviceManagerError::InvalidConsoleFd);
}
}
ConsoleOutputMode::Socket => {
@ -2128,7 +2057,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioConsole)?;
@ -2167,38 +2096,31 @@ impl DeviceManager {
&mut self,
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
virtio_devices: &mut Vec<MetaVirtioDevice>,
serial_pty: Option<PtyPair>,
console_pty: Option<PtyPair>,
#[cfg(target_arch = "x86_64")] debug_console_pty: Option<PtyPair>,
#[cfg(not(target_arch = "x86_64"))] _: Option<PtyPair>,
console_info: Option<ConsoleInfo>,
console_resize_pipe: Option<File>,
) -> DeviceManagerResult<Arc<Console>> {
let serial_config = self.config.lock().unwrap().serial.clone();
if console_info.is_none() {
return Err(DeviceManagerError::InvalidConsoleInfo);
}
//SAFE: console_info is Some, so it's safe to unwrap.
let console_info = console_info.unwrap();
let serial_writer: Option<Box<dyn io::Write + Send>> = match serial_config.mode {
ConsoleOutputMode::File => Some(Box::new(
File::create(serial_config.file.as_ref().unwrap())
.map_err(DeviceManagerError::SerialOutputFileOpen)?,
)),
ConsoleOutputMode::Pty => {
if let Some(pty) = serial_pty.clone() {
self.config.lock().unwrap().serial.file = Some(pty.path.clone());
self.serial_pty = Some(Arc::new(Mutex::new(pty)));
} else {
let (main, sub, path) =
create_pty().map_err(DeviceManagerError::SerialPtyOpen)?;
self.set_raw_mode(&sub)
.map_err(DeviceManagerError::SetPtyRaw)?;
self.config.lock().unwrap().serial.file = Some(path.clone());
self.serial_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
ConsoleOutputMode::File | ConsoleOutputMode::Tty => {
if console_info.serial_main_fd.is_none() {
return Err(DeviceManagerError::InvalidConsoleInfo);
}
None
// SAFETY: serial_main_fd is Some, so it's safe to unwrap.
// SAFETY: serial_main_fd, is a valid FD, it is checked in
// pre_create_console_devices
Some(Box::new(unsafe {
File::from_raw_fd(console_info.serial_main_fd.unwrap())
}))
}
ConsoleOutputMode::Tty => {
let out = stdout();
let _ = self.set_raw_mode(&out);
Some(Box::new(out))
}
ConsoleOutputMode::Off | ConsoleOutputMode::Null | ConsoleOutputMode::Socket => None,
ConsoleOutputMode::Off
| ConsoleOutputMode::Null
| ConsoleOutputMode::Pty
| ConsoleOutputMode::Socket => None,
};
if serial_config.mode != ConsoleOutputMode::Off {
let serial = self.add_serial_device(interrupt_manager, serial_writer)?;
@ -2206,7 +2128,7 @@ impl DeviceManager {
ConsoleOutputMode::Pty | ConsoleOutputMode::Tty | ConsoleOutputMode::Socket => {
let serial_manager = SerialManager::new(
serial,
self.serial_pty.clone(),
console_info.serial_main_fd,
serial_config.mode,
serial_config.socket,
)
@ -2231,43 +2153,34 @@ impl DeviceManager {
#[cfg(target_arch = "x86_64")]
{
let debug_console_config = self.config.lock().unwrap().debug_console.clone();
let debug_console_writer: Option<Box<dyn io::Write + Send>> = match debug_console_config
.mode
{
ConsoleOutputMode::File => Some(Box::new(
File::create(debug_console_config.file.as_ref().unwrap())
.map_err(DeviceManagerError::DebugconOutputFileOpen)?,
)),
ConsoleOutputMode::Pty => {
if let Some(pty) = debug_console_pty {
self.config.lock().unwrap().debug_console.file = Some(pty.path.clone());
self.debug_console_pty = Some(Arc::new(Mutex::new(pty)));
} else {
let (main, sub, path) =
create_pty().map_err(DeviceManagerError::DebugconPtyOpen)?;
self.set_raw_mode(&sub)
.map_err(DeviceManagerError::SetPtyRaw)?;
self.config.lock().unwrap().debug_console.file = Some(path.clone());
self.debug_console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
let debug_console_writer: Option<Box<dyn io::Write + Send>> =
match debug_console_config.mode {
ConsoleOutputMode::File | ConsoleOutputMode::Tty => {
if console_info.debug_main_fd.is_none() {
return Err(DeviceManagerError::InvalidConsoleInfo);
}
// SAFETY: debug_main_fd is Some, so it's safe to unwrap.
// SAFETY: debug_main_fd, is a valid FD, it is checked in
// pre_create_console_devices
Some(Box::new(unsafe {
File::from_raw_fd(console_info.debug_main_fd.unwrap())
}))
}
None
}
ConsoleOutputMode::Tty => {
let out = stdout();
let _ = self.set_raw_mode(&out);
Some(Box::new(out))
}
ConsoleOutputMode::Off | ConsoleOutputMode::Null | ConsoleOutputMode::Socket => {
None
}
};
ConsoleOutputMode::Off
| ConsoleOutputMode::Null
| ConsoleOutputMode::Pty
| ConsoleOutputMode::Socket => None,
};
if let Some(writer) = debug_console_writer {
let _ = self.add_debug_console_device(writer)?;
}
}
let console_resizer =
self.add_virtio_console_device(virtio_devices, console_pty, console_resize_pipe)?;
let console_resizer = self.add_virtio_console_device(
virtio_devices,
console_info.console_main_fd,
console_resize_pipe,
)?;
Ok(Arc::new(Console { console_resizer }))
}
@ -2362,8 +2275,6 @@ impl DeviceManager {
info!("Creating virtio-block device: {:?}", disk_cfg);
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
let (virtio_device, migratable_device) = if disk_cfg.vhost_user {
let socket = disk_cfg.vhost_socket.as_ref().unwrap().clone();
let vu_cfg = VhostUserConfig {
@ -2380,9 +2291,7 @@ impl DeviceManager {
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.force_iommu,
snapshot
.map(|s| s.to_versioned_state())
.transpose()
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
) {
Ok(vub_device) => vub_device,
@ -2542,9 +2451,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
snapshot
.map(|s| s.to_versioned_state())
.transpose()
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
queue_affinity,
)
@ -2601,8 +2508,6 @@ impl DeviceManager {
};
info!("Creating virtio-net device: {:?}", net_cfg);
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
let (virtio_device, migratable_device) = if net_cfg.vhost_user {
let socket = net_cfg.vhost_socket.as_ref().unwrap().clone();
let vu_cfg = VhostUserConfig {
@ -2626,9 +2531,7 @@ impl DeviceManager {
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.force_iommu,
snapshot
.map(|s| s.to_versioned_state())
.transpose()
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
net_cfg.offload_tso,
net_cfg.offload_ufo,
@ -2646,11 +2549,8 @@ impl DeviceManager {
vhost_user_net as Arc<Mutex<dyn Migratable>>,
)
} else {
let state = snapshot
.map(|s| s.to_versioned_state())
.transpose()
let state = state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?;
let virtio_net = if let Some(ref tap_if_name) = net_cfg.tap {
Arc::new(Mutex::new(
virtio_devices::Net::new(
@ -2784,7 +2684,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioRng)?,
@ -2840,7 +2740,7 @@ impl DeviceManager {
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.force_iommu,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioFs)?,
@ -3024,7 +2924,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioPmem)?,
@ -3096,7 +2996,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioVsock)?,
@ -3156,7 +3056,7 @@ impl DeviceManager {
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
virtio_mem_zone.blocks_state().clone(),
versioned_state_from_id(self.snapshot.as_ref(), memory_zone_id.as_str())
state_from_id(self.snapshot.as_ref(), memory_zone_id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioMem)?,
@ -3208,7 +3108,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioBalloon)?,
@ -3252,7 +3152,7 @@ impl DeviceManager {
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVirtioWatchdog)?,
@ -3299,7 +3199,7 @@ impl DeviceManager {
device_path,
self.memory_manager.lock().unwrap().guest_memory(),
vdpa_cfg.num_queues as u16,
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
state_from_id(self.snapshot.as_ref(), id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?,
)
.map_err(DeviceManagerError::CreateVdpa)?,
@ -5010,3 +4910,60 @@ impl Drop for DeviceManager {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_mmio_allocators() {
let res = create_mmio_allocators(0x100000, 0x400000, 1, vec![1], 4 << 10);
assert_eq!(res.len(), 1);
assert_eq!(
res[0].lock().unwrap().base(),
vm_memory::GuestAddress(0x100000)
);
assert_eq!(
res[0].lock().unwrap().end(),
vm_memory::GuestAddress(0x3fffff)
);
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![1, 1], 4 << 10);
assert_eq!(res.len(), 2);
assert_eq!(
res[0].lock().unwrap().base(),
vm_memory::GuestAddress(0x100000)
);
assert_eq!(
res[0].lock().unwrap().end(),
vm_memory::GuestAddress(0x27ffff)
);
assert_eq!(
res[1].lock().unwrap().base(),
vm_memory::GuestAddress(0x280000)
);
assert_eq!(
res[1].lock().unwrap().end(),
vm_memory::GuestAddress(0x3fffff)
);
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![2, 1], 4 << 10);
assert_eq!(res.len(), 2);
assert_eq!(
res[0].lock().unwrap().base(),
vm_memory::GuestAddress(0x100000)
);
assert_eq!(
res[0].lock().unwrap().end(),
vm_memory::GuestAddress(0x2fffff)
);
assert_eq!(
res[1].lock().unwrap().base(),
vm_memory::GuestAddress(0x300000)
);
assert_eq!(
res[1].lock().unwrap().end(),
vm_memory::GuestAddress(0x3fffff)
);
}
}

View File

@ -5,22 +5,15 @@
use crate::cpu::CpuManager;
use zerocopy::AsBytes;
use crate::igvm::loader::Loader;
use crate::igvm::IgvmLoadedInfo;
use crate::igvm::{BootPageAcceptance, StartupMemoryType, HV_PAGE_SIZE};
use crate::igvm::{
loader::Loader, BootPageAcceptance, IgvmLoadedInfo, StartupMemoryType, HV_PAGE_SIZE,
};
use crate::memory_manager::MemoryManager;
use igvm_defs::IgvmPageDataType;
use igvm_defs::IgvmPlatformType;
use igvm_parser::IgvmDirectiveHeader;
use igvm_parser::IgvmFile;
use igvm_parser::IgvmPlatformHeader;
use igvm_parser::IsolationType;
use igvm_defs::IGVM_VHS_PARAMETER;
use igvm_defs::IGVM_VHS_PARAMETER_INSERT;
use igvm_parser::snp_defs::SevVmsa;
pub use mshv_bindings::*;
use igvm::{snp_defs::SevVmsa, IgvmDirectiveHeader, IgvmFile, IgvmPlatformHeader, IsolationType};
use igvm_defs::{
IgvmPageDataType, IgvmPlatformType, IGVM_VHS_PARAMETER, IGVM_VHS_PARAMETER_INSERT,
};
use mshv_bindings::*;
use std::collections::HashMap;
use std::ffi::CString;
use std::io::Read;
@ -42,7 +35,7 @@ pub enum Error {
#[error("failed to read igvm file")]
Igvm(#[source] std::io::Error),
#[error("invalid igvm file")]
InvalidIgvmFile(#[source] igvm_parser::Error),
InvalidIgvmFile(#[source] igvm::Error),
#[error("invalid guest memory map")]
InvalidGuestMemmap(#[source] arch::Error),
#[error("loader error")]

View File

@ -27,8 +27,8 @@
pub mod igvm_loader;
mod loader;
use igvm::snp_defs::SevVmsa;
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
use igvm_parser::snp_defs::SevVmsa;
use zerocopy::FromZeroes;
#[derive(Debug, Clone)]

View File

@ -28,6 +28,7 @@ use anyhow::anyhow;
#[cfg(feature = "dbus_api")]
use api::dbus::{DBusApiOptions, DBusApiShutdownChannels};
use api::http::HttpApiHandle;
use console_devices::{pre_create_console_devices, ConsoleInfo};
use libc::{tcsetattr, termios, EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW};
use memory_manager::MemoryManagerSnapshotData;
use pci::PciBdf;
@ -63,6 +64,7 @@ mod acpi;
pub mod api;
mod clone3;
pub mod config;
pub mod console_devices;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
mod coredump;
pub mod cpu;
@ -548,6 +550,8 @@ pub struct Vmm {
signals: Option<Handle>,
threads: Vec<thread::JoinHandle<()>>,
original_termios_opt: Arc<Mutex<Option<termios>>>,
console_resize_pipe: Option<File>,
console_info: Option<ConsoleInfo>,
}
impl Vmm {
@ -682,6 +686,8 @@ impl Vmm {
signals: None,
threads: vec![],
original_termios_opt: Arc::new(Mutex::new(None)),
console_resize_pipe: None,
console_info: None,
})
}
@ -805,8 +811,6 @@ impl Vmm {
timestamp,
None,
None,
None,
None,
Arc::clone(&self.original_termios_opt),
Some(snapshot),
)
@ -1208,6 +1212,8 @@ impl RequestHandler for Vmm {
// The VM will be created when being asked to boot it.
if self.vm_config.is_none() {
self.vm_config = Some(config);
self.console_info =
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
Ok(())
} else {
Err(VmError::VmAlreadyCreated)
@ -1225,6 +1231,12 @@ impl RequestHandler for Vmm {
return Err(VmError::VmMissingConfig);
};
// console_info is set to None, if the VM was shutdown. Check here and re-create if needed.
if self.console_info.is_none() {
self.console_info =
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
}
// Create a new VM if we don't have one yet.
if self.vm.is_none() {
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
@ -1249,9 +1261,7 @@ impl RequestHandler for Vmm {
&self.seccomp_action,
self.hypervisor.clone(),
activate_evt,
None,
None,
None,
self.console_info.clone(),
None,
Arc::clone(&self.original_termios_opt),
None,
@ -1294,6 +1304,7 @@ impl RequestHandler for Vmm {
}
fn vm_snapshot(&mut self, destination_url: &str) -> result::Result<(), VmError> {
let _ = self.console_info.take();
if let Some(ref mut vm) = self.vm {
vm.snapshot()
.map_err(VmError::Snapshot)
@ -1330,6 +1341,10 @@ impl RequestHandler for Vmm {
.map_err(VmError::Restore)?;
self.vm_config = Some(Arc::clone(&vm_config));
if self.console_info.is_none() {
self.console_info =
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
}
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
@ -1354,8 +1369,6 @@ impl RequestHandler for Vmm {
activate_evt,
None,
None,
None,
None,
Arc::clone(&self.original_termios_opt),
Some(snapshot),
Some(source_url),
@ -1381,6 +1394,7 @@ impl RequestHandler for Vmm {
}
fn vm_shutdown(&mut self) -> result::Result<(), VmError> {
let _ = self.console_info.take();
let r = if let Some(ref mut vm) = self.vm.take() {
vm.shutdown()
} else {
@ -1398,27 +1412,21 @@ impl RequestHandler for Vmm {
event!("vm", "rebooting");
// First we stop the current VM
let (config, serial_pty, console_pty, debug_console_pty, console_resize_pipe) =
if let Some(mut vm) = self.vm.take() {
let config = vm.get_config();
let serial_pty = vm.serial_pty();
let console_pty = vm.console_pty();
let debug_console_pty = vm.debug_console_pty();
let console_resize_pipe = vm
.console_resize_pipe()
.as_ref()
.map(|pipe| pipe.try_clone().unwrap());
vm.shutdown()?;
(
config,
serial_pty,
console_pty,
debug_console_pty,
console_resize_pipe,
)
} else {
return Err(VmError::VmNotCreated);
};
let (config, console_resize_pipe) = if let Some(mut vm) = self.vm.take() {
let config = vm.get_config();
let console_resize_pipe = vm
.console_resize_pipe()
.as_ref()
.map(|pipe| pipe.try_clone().unwrap());
vm.shutdown()?;
(config, console_resize_pipe)
} else {
return Err(VmError::VmNotCreated);
};
// vm.shutdown() closes most of the console devices, so set console_info to None
// so that the closed FDs are not reused.
let _ = self.console_info.take();
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
@ -1439,6 +1447,9 @@ impl RequestHandler for Vmm {
warn!("Spurious second reset event received. Ignoring.");
}
self.console_info =
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
// Then we create the new VM
let mut vm = Vm::new(
config,
@ -1449,9 +1460,7 @@ impl RequestHandler for Vmm {
&self.seccomp_action,
self.hypervisor.clone(),
activate_evt,
serial_pty,
console_pty,
debug_console_pty,
self.console_info.clone(),
console_resize_pipe,
Arc::clone(&self.original_termios_opt),
None,
@ -2151,6 +2160,7 @@ mod unit_tests {
watchdog: false,
#[cfg(feature = "guest_debug")]
gdb: false,
pci_segments: None,
platform: None,
tpm: None,
preserved_fds: None,

View File

@ -39,8 +39,6 @@ use std::result;
use std::sync::{Arc, Barrier, Mutex};
use std::{ffi, thread};
use tracer::trace_scoped;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_devices::BlocksState;
#[cfg(target_arch = "x86_64")]
use vm_allocator::GsiApic;
@ -55,7 +53,7 @@ use vm_memory::{
};
use vm_migration::{
protocol::MemoryRange, protocol::MemoryRangeTable, Migratable, MigratableError, Pausable,
Snapshot, SnapshotData, Snapshottable, Transportable, VersionMapped,
Snapshot, SnapshotData, Snapshottable, Transportable,
};
pub const MEMORY_MANAGER_ACPI_SIZE: usize = 0x18;
@ -82,7 +80,7 @@ const PLATFORM_DEVICE_AREA_SIZE: u64 = 1 << 20;
const MAX_PREFAULT_THREAD_COUNT: usize = 16;
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
#[derive(Clone, Default, Serialize, Deserialize)]
struct HotPlugState {
base: u64,
length: u64,
@ -143,7 +141,7 @@ impl MemoryZone {
pub type MemoryZones = HashMap<String, MemoryZone>;
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[derive(Clone, Serialize, Deserialize)]
struct GuestRamMapping {
slot: u32,
gpa: u64,
@ -153,7 +151,7 @@ struct GuestRamMapping {
file_offset: u64,
}
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[derive(Clone, Serialize, Deserialize)]
struct ArchMemRegion {
base: u64,
size: usize,
@ -1269,7 +1267,7 @@ impl MemoryManager {
memory_file_path.push(String::from(SNAPSHOT_FILENAME));
let mem_snapshot: MemoryManagerSnapshotData =
snapshot.to_versioned_state().map_err(Error::Restore)?;
snapshot.to_state().map_err(Error::Restore)?;
let mm = MemoryManager::new(
vm,
@ -2628,7 +2626,7 @@ impl Aml for MemoryManager {
impl Pausable for MemoryManager {}
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct MemoryManagerSnapshotData {
memory_ranges: MemoryRangeTable,
guest_ram_mappings: Vec<GuestRamMapping>,
@ -2642,8 +2640,6 @@ pub struct MemoryManagerSnapshotData {
next_hotplug_slot: usize,
}
impl VersionMapped for MemoryManagerSnapshotData {}
impl Snapshottable for MemoryManager {
fn id(&self) -> String {
MEMORY_MANAGER_SNAPSHOT_ID.to_string()
@ -2662,7 +2658,7 @@ impl Snapshottable for MemoryManager {
// memory range content for the ranges requiring it.
self.snapshot_memory_ranges = memory_ranges;
Ok(Snapshot::from_data(SnapshotData::new_from_versioned_state(
Ok(Snapshot::from_data(SnapshotData::new_from_state(
&self.snapshot_data(),
)?))
}

View File

@ -168,6 +168,7 @@ mod mshv {
pub const MSHV_GET_VP_STATE: u64 = 0xc010_b80a;
pub const MSHV_SET_VP_STATE: u64 = 0xc010_b80b;
pub const MSHV_SET_PARTITION_PROPERTY: u64 = 0x4010_b80c;
pub const MSHV_GET_PARTITION_PROPERTY: u64 = 0xc010_b80d;
pub const MSHV_GET_GPA_ACCESS_STATES: u64 = 0xc01c_b812;
pub const MSHV_VP_TRANSLATE_GVA: u64 = 0xc020_b80e;
pub const MSHV_CREATE_PARTITION: u64 = 0x4030_b801;
@ -211,6 +212,12 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
Eq,
MSHV_SET_PARTITION_PROPERTY
)?],
and![Cond::new(
1,
ArgLen::Dword,
Eq,
MSHV_GET_PARTITION_PROPERTY
)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_GPA_ACCESS_STATES)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA)?],
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_PARTITION)?],

View File

@ -4,7 +4,6 @@
//
use crate::config::ConsoleOutputMode;
use crate::device_manager::PtyPair;
#[cfg(target_arch = "aarch64")]
use devices::legacy::Pl011;
#[cfg(target_arch = "x86_64")]
@ -14,6 +13,7 @@ use serial_buffer::SerialBuffer;
use std::fs::File;
use std::io::Read;
use std::net::Shutdown;
use std::os::fd::RawFd;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::panic::AssertUnwindSafe;
@ -119,7 +119,7 @@ impl SerialManager {
pub fn new(
#[cfg(target_arch = "x86_64")] serial: Arc<Mutex<Serial>>,
#[cfg(target_arch = "aarch64")] serial: Arc<Mutex<Pl011>>,
pty_pair: Option<Arc<Mutex<PtyPair>>>,
main_fd: Option<RawFd>,
mode: ConsoleOutputMode,
socket: Option<PathBuf>,
) -> Result<Option<Self>> {
@ -127,13 +127,8 @@ impl SerialManager {
let in_file = match mode {
ConsoleOutputMode::Pty => {
if let Some(pty_pair) = pty_pair {
pty_pair
.lock()
.unwrap()
.main
.try_clone()
.map_err(Error::FileClone)?
if let Some(pty_main) = main_fd {
unsafe { File::from_raw_fd(pty_main) }
} else {
return Ok(None);
}
@ -161,12 +156,12 @@ impl SerialManager {
}
}
ConsoleOutputMode::Socket => {
if let Some(path_in_socket) = socket {
socket_path = Some(path_in_socket.clone());
let listener = UnixListener::bind(path_in_socket.as_path())
.map_err(Error::BindUnixSocket)?;
// SAFETY: listener is valid and will return valid fd
unsafe { File::from_raw_fd(listener.into_raw_fd()) }
if let Some(socket_fd) = main_fd {
if let Some(path_in_socket) = socket {
socket_path = Some(path_in_socket.clone());
}
// SAFETY: socket_fd is valid and will return a valid File
unsafe { File::from_raw_fd(socket_fd) }
} else {
return Ok(None);
}

View File

@ -2,13 +2,15 @@
// SPDX-License-Identifier: Apache-2.0
use crate::clone3::{clone3, clone_args, CLONE_CLEAR_SIGHAND};
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use arch::_NSIG;
use hypervisor::HypervisorType;
use libc::{
c_int, c_void, close, fork, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset,
siginfo_t, signal, sigprocmask, syscall, tcgetpgrp, tcsetpgrp, SYS_close_range, EINVAL, ENOSYS,
ENOTTY, O_CLOEXEC, POLLERR, SIGCHLD, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY,
};
use seccompiler::{apply_filter, BpfProgram};
use seccompiler::{apply_filter, BpfProgram, SeccompAction};
use std::cell::RefCell;
use std::collections::BTreeSet;
use std::fs::{read_dir, File};
@ -256,3 +258,16 @@ pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io:
Ok(rx)
}
pub fn listen_for_sigwinch_on_tty(
pty_sub: File,
seccomp_action: &SeccompAction,
hypervisor_type: HypervisorType,
) -> std::io::Result<File> {
let seccomp_filter =
get_seccomp_filter(seccomp_action, Thread::PtyForeground, hypervisor_type).unwrap();
let console_resize_pipe = start_sigwinch_listener(seccomp_filter, pty_sub)?;
Ok(console_resize_pipe)
}

View File

@ -16,12 +16,13 @@ use crate::config::{
UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig,
};
use crate::config::{NumaConfig, PayloadConfig};
use crate::console_devices::{ConsoleDeviceError, ConsoleInfo};
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use crate::coredump::{
CpuElf64Writable, DumpState, Elf64Writable, GuestDebuggable, GuestDebuggableError, NoteDescType,
};
use crate::cpu;
use crate::device_manager::{DeviceManager, DeviceManagerError, PtyPair};
use crate::device_manager::{DeviceManager, DeviceManagerError};
use crate::device_tree::DeviceTree;
#[cfg(feature = "guest_debug")]
use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload};
@ -30,7 +31,7 @@ use crate::igvm::igvm_loader;
use crate::memory_manager::{
Error as MemoryManagerError, MemoryManager, MemoryManagerSnapshotData,
};
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
use crate::migration::get_vm_snapshot;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use crate::migration::url_to_file;
@ -94,7 +95,7 @@ use vm_memory::{
use vm_migration::protocol::{Request, Response, Status};
use vm_migration::{
protocol::MemoryRangeTable, snapshot_from_id, Migratable, MigratableError, Pausable, Snapshot,
SnapshotData, Snapshottable, Transportable,
Snapshottable, Transportable,
};
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
@ -319,6 +320,9 @@ pub enum Error {
#[error("Error injecting NMI")]
ErrorNmi,
#[error("Error creating console devices")]
CreateConsoleDevices(ConsoleDeviceError),
}
pub type Result<T> = result::Result<T, Error>;
@ -457,7 +461,7 @@ pub struct Vm {
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
// The hypervisor abstracted virtual machine.
vm: Arc<dyn hypervisor::Vm>,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
saved_clock: Option<hypervisor::ClockData>,
numa_nodes: NumaNodes,
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
@ -481,9 +485,7 @@ impl Vm {
hypervisor: Arc<dyn hypervisor::Hypervisor>,
activate_evt: EventFd,
timestamp: Instant,
serial_pty: Option<PtyPair>,
console_pty: Option<PtyPair>,
debug_console_pty: Option<PtyPair>,
console_info: Option<ConsoleInfo>,
console_resize_pipe: Option<File>,
original_termios: Arc<Mutex<Option<termios>>>,
snapshot: Option<Snapshot>,
@ -620,7 +622,6 @@ impl Vm {
#[cfg(target_arch = "x86_64")]
io_bus,
mmio_bus,
hypervisor.hypervisor_type(),
vm.clone(),
config.clone(),
memory_manager.clone(),
@ -641,13 +642,7 @@ impl Vm {
device_manager
.lock()
.unwrap()
.create_devices(
serial_pty,
console_pty,
debug_console_pty,
console_resize_pipe,
original_termios,
)
.create_devices(console_info, console_resize_pipe, original_termios)
.map_err(Error::DeviceManager)?;
#[cfg(feature = "tdx")]
@ -671,7 +666,7 @@ impl Vm {
.transpose()
.map_err(Error::InitramfsFile)?;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
let saved_clock = if let Some(snapshot) = snapshot.as_ref() {
let vm_snapshot = get_vm_snapshot(snapshot).map_err(Error::Restore)?;
vm_snapshot.clock
@ -696,7 +691,7 @@ impl Vm {
cpu_manager,
memory_manager,
vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
saved_clock,
numa_nodes,
hypervisor,
@ -798,9 +793,7 @@ impl Vm {
seccomp_action: &SeccompAction,
hypervisor: Arc<dyn hypervisor::Hypervisor>,
activate_evt: EventFd,
serial_pty: Option<PtyPair>,
console_pty: Option<PtyPair>,
debug_console_pty: Option<PtyPair>,
console_info: Option<ConsoleInfo>,
console_resize_pipe: Option<File>,
original_termios: Arc<Mutex<Option<termios>>>,
snapshot: Option<Snapshot>,
@ -878,9 +871,7 @@ impl Vm {
hypervisor,
activate_evt,
timestamp,
serial_pty,
console_pty,
debug_console_pty,
console_info,
console_resize_pipe,
original_termios,
snapshot,
@ -1356,18 +1347,6 @@ impl Vm {
Ok(())
}
pub fn serial_pty(&self) -> Option<PtyPair> {
self.device_manager.lock().unwrap().serial_pty()
}
pub fn console_pty(&self) -> Option<PtyPair> {
self.device_manager.lock().unwrap().console_pty()
}
pub fn debug_console_pty(&self) -> Option<PtyPair> {
self.device_manager.lock().unwrap().debug_console_pty()
}
pub fn console_resize_pipe(&self) -> Option<Arc<File>> {
self.device_manager.lock().unwrap().console_resize_pipe()
}
@ -2468,7 +2447,7 @@ impl Pausable for Vm {
.valid_transition(new_state)
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
{
let mut clock = self
.vm
@ -2506,7 +2485,7 @@ impl Pausable for Vm {
.map_err(|e| MigratableError::Resume(anyhow!("Invalid transition: {:?}", e)))?;
self.cpu_manager.lock().unwrap().resume()?;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
{
if let Some(clock) = &self.saved_clock {
self.vm.set_clock(clock).map_err(|e| {
@ -2525,7 +2504,7 @@ impl Pausable for Vm {
#[derive(Serialize, Deserialize)]
pub struct VmSnapshot {
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
#[cfg(target_arch = "x86_64")]
pub clock: Option<hypervisor::ClockData>,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
pub common_cpuid: Vec<hypervisor::arch::x86::CpuIdEntry>,
@ -2579,15 +2558,14 @@ impl Snapshottable for Vm {
})?
};
let vm_snapshot_data = serde_json::to_vec(&VmSnapshot {
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
let vm_snapshot_state = VmSnapshot {
#[cfg(target_arch = "x86_64")]
clock: self.saved_clock,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
common_cpuid,
})
.map_err(|e| MigratableError::Snapshot(e.into()))?;
};
let mut vm_snapshot = Snapshot::from_data(SnapshotData(vm_snapshot_data));
let mut vm_snapshot = Snapshot::new_from_state(&vm_snapshot_state)?;
let (id, snapshot) = {
let mut cpu_manager = self.cpu_manager.lock().unwrap();
@ -3247,17 +3225,11 @@ pub fn test_vm() {
loop {
match vcpu.run().expect("run failed") {
VmExit::IoOut(addr, data) => {
println!(
"IO out -- addr: {:#x} data [{:?}]",
addr,
str::from_utf8(data).unwrap()
);
}
VmExit::Reset => {
println!("HLT");
break;
}
VmExit::Ignore => {}
r => panic!("unexpected exit reason: {r:?}"),
}
}

View File

@ -94,6 +94,22 @@ pub struct PlatformConfig {
pub sev_snp: bool,
}
pub const DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT: u32 = 1;
fn default_pci_segment_aperture_weight() -> u32 {
DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct PciSegmentConfig {
#[serde(default)]
pub pci_segment: u16,
#[serde(default = "default_pci_segment_aperture_weight")]
pub mmio32_aperture_weight: u32,
#[serde(default = "default_pci_segment_aperture_weight")]
pub mmio64_aperture_weight: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct MemoryZoneConfig {
pub id: String,
@ -620,6 +636,7 @@ pub struct VmConfig {
#[cfg(feature = "guest_debug")]
#[serde(default)]
pub gdb: bool,
pub pci_segments: Option<Vec<PciSegmentConfig>>,
pub platform: Option<PlatformConfig>,
pub tpm: Option<TpmConfig>,
// Preserved FDs are the ones that share the same life-time as its holding