Compare commits

..

13 Commits
v37.0 ... v36.1

Author SHA1 Message Date
Bo Chen
d725400158 build: Release v36.1 (bug fix release)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-01-10 11:36:39 -08:00
Bo Chen
7026a08569 tests: Temporarily disable vhost_user_blk tests on aarch64
See: #5934

Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit 62db13ba0e)
2024-01-10 09:09:15 -08:00
Michael Zhao
b6945b649a scripts: Workaround random wget failures on AArch64
Random failures of downloading `cloud-hypervisor-static-aarch64` with
`wget` were seen. The commit applies a workaround to retry the download
for a few times.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
(cherry picked from commit f0c5592ba1)
2024-01-10 09:09:15 -08:00
Ravi kumar Veeramally
4c0052f355 tests: Migrate docker container from ubuntu 20.04 to 22.04
The following tests have been temporarily disabled:

1. Live upgrade/migration test with ovs-dpdk (#5532);
2. Disk hotplug tests on windows guests (#6037);

This patch has been tested with PR #6048.

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
Tested-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit 24f384d239)
2024-01-10 09:09:15 -08:00
Bo Chen
758930bc65 virtio-devices: Fix beta clippy issue
error: use of a fallible conversion when an infallible one could be used
Error:    --> virtio-devices/src/vhost_user/vu_common_ctrl.rs:206:51
    |
206 |             let actual_size: usize = queue.size().try_into().unwrap();
    |                                                   ^^^^^^^^^^^^^^^^^^^ help: use: `into()`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
    = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`

error: could not compile `virtio-devices` (lib) due to previous error
Error: warning: build failed, waiting for other jobs to finish...
error: could not compile `virtio-devices` (lib test) due to previous error
Error: The process '/home/runner/.cargo/bin/cargo' failed with exit code 101

Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit d4a163dd39)
2024-01-10 09:09:15 -08:00
Yi Wang
7b46d06171 build: fix clippy ptr arg issue
CI reports errors:

error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
    --> arch/src/x86_64/mod.rs:1351:19
     |
1351 |     epc_sections: &Vec<SgxEpcSection>,
     |                   ^^^^^^^^^^^^^^^^^^^ help: change this to: `&[SgxEpcSection]`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
     = note: `-D clippy::ptr-arg` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::ptr_arg)]`

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit 3d6594a594)
2024-01-10 09:09:15 -08:00
Yi Wang
e16b06f894 build: fix clippy Path::join issue
CI reports clippy errors:

error: argument to `Path::join` starts with a path separator
    --> tests/integration.rs:4076:58
     |
4076 |         let serial_socket = guest.tmp_dir.as_path().join("/tmp/serial.socket");
     |                                                          ^^^^^^^^^^^^^^^^^^^^
     |
     = note: joining a path starting with separator will replace the path instead
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#join_absolute_paths

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit ee2f0c3cb4)
2024-01-10 09:09:15 -08:00
Yi Wang
4e001e2ad5 build: fix clippy complex closures issue
CI reports clippy errors:

error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
   --> test_infra/src/lib.rs:93:51
    |
93  |           match (|| -> Result<(), WaitForBootError> {
    |  ___________________________________________________^
94  | |             let listener =
95  | |                 TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
96  | |             listener
...   |
145 | |             }
146 | |         })() {
    | |_________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions
    = note: `-D clippy::blocks-in-conditions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]`

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit 9c2d650cb8)
2024-01-10 09:09:15 -08:00
Bo Chen
e309ed0a38 test: Enable live-upgrade based on release v36.0
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-01-10 09:09:15 -08:00
Bo Chen
948e7ca61a vmm: tdx: Error out early for TD migration
Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit e64b66054e)
2024-01-10 09:09:15 -08:00
Rui Chang
920564b281 vmm: add add-user-device support in cloud-hypervisor.yaml
The change is missed when add "add-user-device" support in
53b2e19934, use this commit to fix it.

Signed-off-by: Rui Chang <rui.chang@arm.com>
(cherry picked from commit 2b457584e0)
2024-01-10 09:09:15 -08:00
Thomas Barrett
014c19e189 devices: fix pv_panic alignment
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
(cherry picked from commit 5f3ff3c44a)
2024-01-10 09:09:15 -08:00
Thomas Barrett
dbf4891eb2 block: fix aio backend behavior when writeback enabled
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
(cherry picked from commit d9ed281719)
2024-01-10 09:09:15 -08:00
87 changed files with 899 additions and 2417 deletions

View File

@@ -9,7 +9,7 @@ jobs:
name: Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v1
- uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -13,13 +13,13 @@ jobs:
- stable
- beta
- nightly
- "1.70"
- "1.66"
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 0
@@ -54,9 +54,6 @@ jobs:
- name: Build (sev_snp)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (igvm)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (mshv + kvm)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks

View File

@@ -5,7 +5,7 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Set up Python 3.x
uses: actions/setup-python@v1
with:

View File

@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1

View File

@@ -14,7 +14,7 @@ jobs:
- x86_64-unknown-linux-gnu
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Install Rust toolchain (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with:

View File

@@ -1,26 +0,0 @@
name: Commit messages check
on:
pull_request:
jobs:
gitlint:
name: Check commit messages
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade gitlint
- name: Lint git commit messages
run: |
gitlint --commits origin/$GITHUB_BASE_REF..

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Lint Dockerfile
uses: hadolint/hadolint-action@master

View File

@@ -1,16 +0,0 @@
name: Cloud Hypervisor OpenAPI Validation
on:
pull_request:
jobs:
Validate:
runs-on: ubuntu-latest
container: openapitools/openapi-generator-cli
steps:
- uses: actions/checkout@v4
- name: Validate OpenAPI
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
/usr/local/bin/docker-entrypoint.sh validate -i vmm/src/api/openapi/cloud-hypervisor.yaml

View File

@@ -34,7 +34,7 @@ jobs:
experimental: true
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@@ -109,14 +109,6 @@ jobs:
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (igvm)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (kvm + tdx)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
@@ -133,6 +125,6 @@ jobs:
name: Typos / Spellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
# Executes "typos ."
- uses: crate-ci/typos@v1.16.11

View File

@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Install musl-gcc
run: sudo apt install -y musl-tools
- name: Create release directory
@@ -16,29 +16,29 @@ jobs:
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.70"
toolchain: "1.67.1"
target: x86_64-unknown-linux-gnu
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.70"
toolchain: "1.67.1"
target: x86_64-unknown-linux-musl
- name: Build
uses: actions-rs/cargo@v1
with:
toolchain: "1.70"
toolchain: "1.67.1"
command: build
args: --all --release --features mshv --target=x86_64-unknown-linux-gnu
- name: Static Build
uses: actions-rs/cargo@v1
with:
toolchain: "1.70"
toolchain: "1.67.1"
command: build
args: --all --release --features mshv --target=x86_64-unknown-linux-musl
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.70"
toolchain: "1.67.1"
target: aarch64-unknown-linux-musl
override: true
- name: Create Release

View File

@@ -1,15 +0,0 @@
[general]
extra-path=scripts/gitlint/rules.py
regex-style-search=true
[ignore-by-author-name]
regex=dependabot
ignore=all
# default 72
[title-max-length]
line-length=72
# default 80
[body-max-line-length]
line-length=72

235
Cargo.lock generated
View File

@@ -36,15 +36,16 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.4"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
@@ -74,9 +75,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "3.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
@@ -146,15 +147,15 @@ dependencies = [
[[package]]
name = "async-executor"
version = "1.8.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c"
checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb"
dependencies = [
"async-lock 3.2.0",
"async-lock",
"async-task",
"concurrent-queue",
"fastrand 2.0.0",
"futures-lite 2.1.0",
"fastrand 1.9.0",
"futures-lite",
"slab",
]
@@ -164,10 +165,10 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
dependencies = [
"async-lock 2.7.0",
"async-lock",
"autocfg",
"blocking",
"futures-lite 1.13.0",
"futures-lite",
]
[[package]]
@@ -176,15 +177,15 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
dependencies = [
"async-lock 2.7.0",
"async-lock",
"autocfg",
"cfg-if",
"concurrent-queue",
"futures-lite 1.13.0",
"futures-lite",
"log",
"parking",
"polling",
"rustix 0.37.27",
"rustix 0.37.25",
"slab",
"socket2",
"waker-fn",
@@ -199,17 +200,6 @@ dependencies = [
"event-listener 2.5.3",
]
[[package]]
name = "async-lock"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c"
dependencies = [
"event-listener 4.0.0",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-process"
version = "1.8.0"
@@ -217,21 +207,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf012553ce51eb7aa6dc2143804cc8252bd1cb681a1c5cb7fa94ca88682dee1d"
dependencies = [
"async-io",
"async-lock 2.7.0",
"async-lock",
"async-signal",
"blocking",
"cfg-if",
"event-listener 3.0.0",
"futures-lite 1.13.0",
"futures-lite",
"rustix 0.38.8",
"windows-sys 0.48.0",
]
[[package]]
name = "async-recursion"
version = "1.0.5"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
dependencies = [
"proc-macro2",
"quote",
@@ -245,7 +235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c99f3cb3f9ff89f7d718fbb942c9eb91bedff12e396adf09a622dfe7ffec2bc2"
dependencies = [
"async-io",
"async-lock 2.7.0",
"async-lock",
"atomic-waker",
"cfg-if",
"concurrent-queue",
@@ -259,9 +249,9 @@ dependencies = [
[[package]]
name = "async-task"
version = "4.5.0"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1"
checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
[[package]]
name = "async-trait"
@@ -371,11 +361,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
dependencies = [
"async-channel",
"async-lock 2.7.0",
"async-lock",
"async-task",
"atomic-waker",
"fastrand 1.9.0",
"futures-lite 1.13.0",
"futures-lite",
"log",
]
@@ -408,35 +398,36 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.4.7"
version = "4.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.4.7"
version = "4.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"once_cell",
"strsim",
"terminal_size",
]
[[package]]
name = "clap_lex"
version = "0.6.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
[[package]]
name = "cloud-hypervisor"
version = "37.0.0"
version = "36.1.0"
dependencies = [
"anyhow",
"api_client",
@@ -473,9 +464,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "concurrent-queue"
version = "2.3.0"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400"
checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
dependencies = [
"crossbeam-utils",
]
@@ -727,27 +718,6 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "event-listener"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3"
dependencies = [
"event-listener 4.0.0",
"pin-project-lite",
]
[[package]]
name = "event_monitor"
version = "0.1.0"
@@ -826,9 +796,9 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.29"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
@@ -862,19 +832,6 @@ dependencies = [
"waker-fn",
]
[[package]]
name = "futures-lite"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143"
dependencies = [
"fastrand 2.0.0",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]]
name = "futures-macro"
version = "0.3.28"
@@ -894,9 +851,9 @@ checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.29"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-util"
@@ -918,11 +875,11 @@ dependencies = [
[[package]]
name = "gdbstub"
version = "0.7.0"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09a8b954f9d02b74fe8e89a1c77bd9a6b8206713ebf1b272bfad9573b4a86f88"
checksum = "f4e02bf1b1a624d96925c608f1b268d82a76cbc587ce9e59f7c755e9ea11c75c"
dependencies = [
"bitflags 2.4.1",
"bitflags 1.3.2",
"cfg-if",
"log",
"managed",
@@ -932,9 +889,9 @@ dependencies = [
[[package]]
name = "gdbstub_arch"
version = "0.3.0"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e3b1357bd3203fc09a6601327ae0ab38865d14231d0b65d3143f5762cc7977d"
checksum = "eecb536c55c43593a00dde9074dbbdb0e81ce5f20dbca921400f8779c21dea9c"
dependencies = [
"gdbstub",
"num-traits",
@@ -1067,9 +1024,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.1.0"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [
"equivalent",
"hashbrown",
@@ -1097,9 +1054,9 @@ dependencies = [
[[package]]
name = "io-uring"
version = "0.6.2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460648e47a07a43110fbfa2e0b14afb2be920093c31e5dccc50e49568e099762"
checksum = "141a0f4546a50b2ed637c7a6df0d7dff45c9f41523254996764461c8ae0d9424"
dependencies = [
"bitflags 1.3.2",
"libc",
@@ -1200,9 +1157,9 @@ dependencies = [
[[package]]
name = "linux-loader"
version = "0.10.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "132a531b85b3a164012ab682c72f8f2cce7757f187be5f60782fd2b4cda9cb34"
checksum = "1db6a725c8000971f83fa93ed7ee1b600e55a1471a2a653379d3c84f72effdcf"
dependencies = [
"vm-memory",
]
@@ -1231,9 +1188,12 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "managed"
@@ -1259,7 +1219,7 @@ dependencies = [
[[package]]
name = "micro_http"
version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#a4d632f2c5ea45712c0d2002dc909a63879e85c3"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#0d0fdcd50ea10c1b4777f9a958873fc848a5b7bb"
dependencies = [
"libc",
"vmm-sys-util",
@@ -1287,7 +1247,7 @@ dependencies = [
[[package]]
name = "mshv-bindings"
version = "0.1.1"
source = "git+https://github.com/rust-vmm/mshv?branch=main#0dd4d3452a7f2e95199f4b58380acc41458474de"
source = "git+https://github.com/rust-vmm/mshv?branch=main#af397ea8514303d3a19d21d33730e867f7415ba9"
dependencies = [
"libc",
"serde",
@@ -1299,7 +1259,7 @@ dependencies = [
[[package]]
name = "mshv-ioctls"
version = "0.1.1"
source = "git+https://github.com/rust-vmm/mshv?branch=main#0dd4d3452a7f2e95199f4b58380acc41458474de"
source = "git+https://github.com/rust-vmm/mshv?branch=main#af397ea8514303d3a19d21d33730e867f7415ba9"
dependencies = [
"libc",
"mshv-bindings",
@@ -1367,18 +1327,18 @@ checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
[[package]]
name = "num-traits"
version = "0.2.17"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.30.4"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
@@ -1453,9 +1413,9 @@ dependencies = [
[[package]]
name = "parking"
version = "2.2.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067"
[[package]]
name = "parking_lot"
@@ -1549,18 +1509,18 @@ dependencies = [
[[package]]
name = "pin-project"
version = "1.1.3"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.3"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [
"proc-macro2",
"quote",
@@ -1710,9 +1670,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.70"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]
@@ -1863,9 +1823,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.37.27"
version = "0.37.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035"
dependencies = [
"bitflags 1.3.2",
"errno",
@@ -1948,9 +1908,9 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.17"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
dependencies = [
"proc-macro2",
"quote",
@@ -2127,11 +2087,11 @@ dependencies = [
[[package]]
name = "terminal_size"
version = "0.3.0"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
dependencies = [
"rustix 0.38.8",
"rustix 0.37.25",
"windows-sys 0.48.0",
]
@@ -2178,9 +2138,9 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
[[package]]
name = "toml_datetime"
version = "0.6.5"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
[[package]]
name = "toml_edit"
@@ -2267,9 +2227,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "utf8parse"
@@ -2328,7 +2288,7 @@ dependencies = [
[[package]]
name = "vfio-bindings"
version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#59c604fa6e42080f0a47c124ba29454fe4cb7475"
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [
"vmm-sys-util",
]
@@ -2336,7 +2296,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#59c604fa6e42080f0a47c124ba29454fe4cb7475"
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [
"byteorder",
"kvm-bindings",
@@ -2354,7 +2314,7 @@ dependencies = [
[[package]]
name = "vfio_user"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#6c72e997e61d9e84b8ee691ad63ece6c717cf5aa"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#2d96b90a7279547356ad8f83aaa3115ad5497302"
dependencies = [
"bitflags 1.3.2",
"libc",
@@ -2370,11 +2330,11 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.9.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "289adfce099c71f8310f895932ccd978f352ca494ea47496dbe20d4241888b82"
checksum = "61957aeb36daf0b00b87fff9c10dd28a161bd35ab157553d340d183b3d8756e6"
dependencies = [
"bitflags 2.4.1",
"bitflags 1.3.2",
"libc",
"vm-memory",
"vmm-sys-util",
@@ -2382,9 +2342,9 @@ dependencies = [
[[package]]
name = "vhost-user-backend"
version = "0.11.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61255322e3ebe93fb77d9f6d99577eca7089bbea4174076c5353a8024a463061"
checksum = "ab069cdedaf18a0673766eb0a07a0f4ee3ed1b8e17fbfe4aafe5b988e2de1d01"
dependencies = [
"libc",
"log",
@@ -2434,9 +2394,9 @@ dependencies = [
[[package]]
name = "virtio-bindings"
version = "0.2.2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "878bcb1b2812a10c30d53b0ed054999de3d98f25ece91fc173973f9c57aaae86"
checksum = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98"
[[package]]
name = "virtio-devices"
@@ -2474,9 +2434,9 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.10.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73a01db2cfb6c4b9bc20608b1336263d16714ea8db05de9fec2a254e076f9385"
checksum = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f"
dependencies = [
"log",
"virtio-bindings",
@@ -2513,9 +2473,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#77212bd0d62913e445c
[[package]]
name = "vm-memory"
version = "0.13.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5376c9ee5ebe2103a310d8241936cfb93c946734b0479a4fa5bdf7a64abbacd8"
checksum = "9dc276f0d00c17b9aeb584da0f1e1c673df0d183cc2539e3636ec8cbc5eae99b"
dependencies = [
"arc-swap",
"libc",
@@ -2565,20 +2525,15 @@ dependencies = [
"futures",
"gdbstub",
"gdbstub_arch",
"hex",
"hypervisor",
"igvm",
"igvm_defs",
"libc",
"linux-loader",
"log",
"micro_http",
"mshv-bindings",
"net_util",
"once_cell",
"option_parser",
"pci",
"range_map_vec",
"seccompiler",
"serde",
"serde_json",
@@ -2882,7 +2837,7 @@ dependencies = [
"async-executor",
"async-fs",
"async-io",
"async-lock 2.7.0",
"async-lock",
"async-process",
"async-recursion",
"async-task",

View File

@@ -1,6 +1,6 @@
[package]
name = "cloud-hypervisor"
version = "37.0.0"
version = "36.1.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.70"
rust-version = "1.66"
[profile.release]
lto = true
@@ -31,13 +31,13 @@ debug = true
[dependencies]
anyhow = "1.0.75"
api_client = { path = "api_client" }
clap = { version = "4.4.7", features = ["string"] }
clap = { version = "4.3.11", features = ["string"] }
dhat = { version = "0.3.2", optional = true }
epoll = "4.3.3"
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
libc = "0.2.147"
log = { version = "0.4.20", features = ["std"] }
log = { version = "0.4.17", features = ["std"] }
option_parser = { path = "option_parser" }
seccompiler = "0.4.0"
serde_json = "1.0.107"
@@ -47,7 +47,7 @@ tpm = { path = "tpm"}
tracer = { path = "tracer" }
vmm = { path = "vmm" }
vmm-sys-util = "0.11.0"
vm-memory = "0.13.1"
vm-memory = "0.12.2"
zbus = { version = "3.11.1", optional = true }
# List of patched crates
@@ -71,11 +71,10 @@ default = ["kvm", "io_uring"]
dbus_api = ["zbus", "vmm/dbus_api"]
dhat-heap = ["dhat"] # For heap profiling
guest_debug = ["vmm/guest_debug"]
igvm = ["vmm/igvm", "mshv"]
io_uring = ["vmm/io_uring"]
kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"]
sev_snp = ["igvm", "vmm/sev_snp", "mshv"]
sev_snp = ["vmm/sev_snp", "mshv"]
tdx = ["vmm/tdx"]
tracing = ["vmm/tracing", "tracer/tracing"]

31
Jenkinsfile vendored
View File

@@ -53,9 +53,6 @@ pipeline {
return runWorkers
}
}
environment {
AUTH_DOWNLOAD_TOKEN = credentials('8a26fd74-d40e-414c-9132-ff3f867806ef')
}
stages {
stage('Checkout') {
steps {
@@ -67,6 +64,11 @@ pipeline {
sh 'scripts/prepare_vdpa.sh'
}
}
stage('Run OpenAPI tests') {
steps {
sh 'scripts/run_openapi_tests.sh'
}
}
stage('Run unit tests') {
steps {
sh 'scripts/dev_cli.sh tests --unit'
@@ -123,9 +125,6 @@ pipeline {
return runWorkers
}
}
environment {
AUTH_DOWNLOAD_TOKEN = credentials('8a26fd74-d40e-414c-9132-ff3f867806ef')
}
stages {
stage('Checkout') {
steps {
@@ -365,9 +364,6 @@ pipeline {
}
}
}
environment {
AUTH_DOWNLOAD_TOKEN = credentials('8a26fd74-d40e-414c-9132-ff3f867806ef')
}
stages {
stage('Checkout') {
steps {
@@ -409,9 +405,6 @@ pipeline {
}
}
}
environment {
AUTH_DOWNLOAD_TOKEN = credentials('8a26fd74-d40e-414c-9132-ff3f867806ef')
}
stages {
stage('Checkout') {
steps {
@@ -512,19 +505,5 @@ def boolean skipWorkerBuild() {
return true
}
if (sh(
returnStatus: true,
script: "git diff --name-only origin/${env.CHANGE_TARGET}... | grep -v '^\\.'"
) != 0) {
return true
}
if (sh(
returnStatus: true,
script: "git diff --name-only origin/${env.CHANGE_TARGET}... | grep -v 'gitlint'"
) != 0) {
return true
}
return false
}

View File

@@ -14,14 +14,14 @@ anyhow = "1.0.75"
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
libc = "0.2.147"
linux-loader = { version = "0.10.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.20"
linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
log = "0.4.17"
serde = { version = "1.0.168", features = ["rc", "derive"] }
thiserror = "1.0.40"
uuid = "1.3.4"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-bitmap"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }

View File

@@ -1,9 +1,8 @@
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
use std::io::{Read, Seek, SeekFrom};
use std::os::fd::AsFd;
use std::result;
use vm_memory::{GuestAddress, GuestMemory};
use vm_memory::{Bytes, GuestAddress, GuestMemory};
/// Errors thrown while loading UEFI binary
#[derive(Debug)]
@@ -25,7 +24,7 @@ pub fn load_uefi<F, M: GuestMemory>(
uefi_image: &mut F,
) -> Result<()>
where
F: Read + Seek + AsFd,
F: Read + Seek,
{
let uefi_size = uefi_image
.seek(SeekFrom::End(0))
@@ -37,6 +36,6 @@ where
}
uefi_image.rewind().map_err(|_| Error::SeekUefiStart)?;
guest_mem
.read_exact_volatile_from(guest_addr, &mut uefi_image.as_fd(), uefi_size)
.read_exact_from(guest_addr, uefi_image, uefi_size)
.map_err(|_| Error::ReadUefiImage)
}

View File

@@ -91,9 +91,8 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use x86_64::{
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry,
EntryPoint, _NSIG,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, EntryPoint, _NSIG,
};
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.

View File

@@ -926,112 +926,6 @@ pub fn configure_system(
)
}
type RamRange = (u64, u64);
/// Returns usable physical memory ranges for the guest
/// These should be used to create e820_RAM memory maps
///
/// There are up to two usable physical memory ranges,
/// divided by the gap at the end of 32bit address space.
pub fn generate_ram_ranges(
guest_mem: &GuestMemoryMmap,
) -> super::Result<(RamRange, Option<RamRange>)> {
// Merge continuous memory regions into one region.
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
let ram_regions = {
let mut ram_regions = Vec::new();
let mut current_start = guest_mem
.iter()
.next()
.map(GuestMemoryRegion::start_addr)
.expect("GuestMemory must have one memory region at least")
.raw_value();
let mut current_end = current_start;
for (start, size) in guest_mem
.iter()
.map(|m| (m.start_addr().raw_value(), m.len()))
{
if current_end == start {
// This zone is continuous with the previous one.
current_end += size;
} else {
ram_regions.push((current_start, current_end));
current_start = start;
current_end = start + size;
}
}
ram_regions.push((current_start, current_end));
ram_regions
};
if ram_regions.len() > 2 {
error!(
"There should be up to two usable physical memory ranges, devidided by the
gap at the end of 32bit address space (e.g. between 3G and 4G)."
);
return Err(super::Error::MemmapTableSetup);
}
// Generate the first usable physical memory range before the gap
let first_ram_range = {
let (first_region_start, first_region_end) =
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
let high_ram_start = layout::HIGH_RAM_START.raw_value();
let mem_32bit_reserved_start = layout::MEM_32BIT_RESERVED_START.raw_value();
if !((first_region_start <= &high_ram_start)
&& (first_region_end > &high_ram_start)
&& (first_region_end <= &mem_32bit_reserved_start))
{
error!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"first usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
high_ram_start, first_region_end
);
(high_ram_start, *first_region_end)
};
// Generate the second usable physical memory range after the gap if any
let second_ram_range = if let Some((second_region_start, second_region_end)) =
ram_regions.get(1)
{
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
if second_region_start != &ram_64bit_start {
error!(
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
second_region_start, ram_64bit_start
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"Second usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
ram_64bit_start, second_region_end
);
Some((ram_64bit_start, *second_region_end))
} else {
None
};
Ok((first_ram_range, second_ram_range))
}
fn configure_pvh(
guest_mem: &GuestMemoryMmap,
cmdline_addr: GuestAddress,
@@ -1078,31 +972,100 @@ fn configure_pvh(
// Create the memory map entries.
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
// Get usable physical memory ranges
let (first_ram_range, second_ram_range) = generate_ram_ranges(guest_mem)?;
// Merge continuous memory regions into one region.
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
let ram_regions = {
let mut ram_regions = Vec::new();
let mut current_start = guest_mem
.iter()
.next()
.map(GuestMemoryRegion::start_addr)
.expect("GuestMemory must have one memory region at least")
.raw_value();
let mut current_end = current_start;
// Create e820 memory map entry before the gap
info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
first_ram_range.0, first_ram_range.1
);
add_memmap_entry(
&mut memmap,
first_ram_range.0,
first_ram_range.1 - first_ram_range.0,
E820_RAM,
);
for (start, size) in guest_mem
.iter()
.map(|m| (m.start_addr().raw_value(), m.len()))
{
if current_end == start {
// This zone is continuous with the previous one.
current_end += size;
} else {
ram_regions.push((current_start, current_end));
current_start = start;
current_end = start + size;
}
}
ram_regions.push((current_start, current_end));
ram_regions
};
if ram_regions.len() > 2 {
error!(
"There should be up to two non-continuous regions, devidided by the
gap at the end of 32bit address space (e.g. between 3G and 4G)."
);
return Err(super::Error::MemmapTableSetup);
}
// Create the memory map entry for memory region before the gap
{
let (first_region_start, first_region_end) =
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
let high_ram_start = layout::HIGH_RAM_START.raw_value();
let mem_32bit_reserved_start = layout::MEM_32BIT_RESERVED_START.raw_value();
if !((first_region_start <= &high_ram_start)
&& (first_region_end > &high_ram_start)
&& (first_region_end <= &mem_32bit_reserved_start))
{
error!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
);
return Err(super::Error::MemmapTableSetup);
}
// Create e820 memory map after the gap if any
if let Some(second_ram_range) = second_ram_range {
info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
second_ram_range.0, second_ram_range.1
high_ram_start, first_region_end
);
add_memmap_entry(
&mut memmap,
high_ram_start,
first_region_end - high_ram_start,
E820_RAM,
);
}
// Create the memory map entry for memory region after the gap if any
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
if second_region_start != &ram_64bit_start {
error!(
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
second_region_start, ram_64bit_start
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
ram_64bit_start, second_region_end
);
add_memmap_entry(
&mut memmap,
second_ram_range.0,
second_ram_range.1 - second_ram_range.0,
ram_64bit_start,
second_region_end - ram_64bit_start,
E820_RAM,
);
}
@@ -1348,7 +1311,7 @@ fn update_cpuid_topology(
// sections exposed to the guest.
fn update_cpuid_sgx(
cpuid: &mut Vec<CpuIdEntry>,
epc_sections: &Vec<SgxEpcSection>,
epc_sections: &[SgxEpcSection],
) -> Result<(), Error> {
// Something's wrong if there's no EPC section.
if epc_sections.is_empty() {

View File

@@ -9,6 +9,7 @@ use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::mpspec;
use crate::GuestMemoryMmap;
use libc::c_char;
use std::io;
use std::mem;
use std::result;
use std::slice;
@@ -153,7 +154,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
return Err(Error::AddressOverflow);
}
mem.read_exact_volatile_from(base_mp, &mut vec![0; mp_size].as_slice(), mp_size)
mem.read_exact_from(base_mp, &mut io::repeat(0), mp_size)
.map_err(Error::Clear)?;
{
@@ -290,10 +291,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
mod tests {
use super::*;
use crate::layout::MPTABLE_START;
use vm_memory::{
bitmap::BitmapSlice, GuestAddress, GuestUsize, VolatileMemoryError, VolatileSlice,
WriteVolatile,
};
use vm_memory::{GuestAddress, GuestUsize};
fn table_entry_size(type_: u8) -> usize {
match type_ as u32 {
@@ -353,24 +351,20 @@ mod tests {
let mpc_table: MpcTableWrapper = mem.read_obj(mpc_offset).unwrap();
struct Sum(u8);
impl WriteVolatile for Sum {
fn write_volatile<B: BitmapSlice>(
&mut self,
buf: &VolatileSlice<B>,
) -> result::Result<usize, VolatileMemoryError> {
let mut tmp = vec![0u8; buf.len()];
tmp.write_all_volatile(buf)?;
for v in tmp.iter() {
impl io::Write for Sum {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
for v in buf.iter() {
self.0 = self.0.wrapping_add(*v);
}
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
let mut sum = Sum(0);
mem.write_volatile_to(mpc_offset, &mut sum, mpc_table.0.length as usize)
mem.write_to(mpc_offset, &mut sum, mpc_table.0.length as usize)
.unwrap();
assert_eq!(sum.0, 0);
}

View File

@@ -11,9 +11,9 @@ io_uring = ["dep:io-uring"]
[dependencies]
byteorder = "1.4.3"
crc32c = "0.6.4"
io-uring = { version = "0.6.2", optional = true }
io-uring = { version = "0.6.1", optional = true }
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
remain = "0.2.11"
smallvec = "1.11.0"
thiserror = "1.0.40"
@@ -21,7 +21,7 @@ uuid = { version = "1.3.4", features = ["v4"] }
versionize = "0.1.10"
versionize_derive = "0.1.4"
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.10.0"
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
virtio-queue = "0.9.0"
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.11.0"

View File

@@ -143,14 +143,10 @@ pub enum ExecuteError {
Flush(io::Error),
#[error("Failed to read: {0}")]
Read(GuestMemoryError),
#[error("Failed to read_exact: {0}")]
ReadExact(io::Error),
#[error("Failed to seek: {0}")]
Seek(io::Error),
#[error("Failed to write: {0}")]
Write(GuestMemoryError),
#[error("Failed to write_all: {0}")]
WriteAll(io::Error),
#[error("Unsupported request: {0}")]
Unsupported(u32),
#[error("Failed to submit io uring: {0}")]
@@ -173,10 +169,8 @@ impl ExecuteError {
ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::ReadExact(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::WriteAll(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP,
ExecuteError::SubmitIoUring(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::GetHostAddress(_) => VIRTIO_BLK_S_IOERR,
@@ -357,21 +351,13 @@ impl Request {
match self.request_type {
RequestType::In => {
let mut buf = vec![0u8; *data_len as usize];
disk.read_exact(&mut buf).map_err(ExecuteError::ReadExact)?;
mem.read_exact_volatile_from(
*data_addr,
&mut buf.as_slice(),
*data_len as usize,
)
.map_err(ExecuteError::Read)?;
mem.read_exact_from(*data_addr, disk, *data_len as usize)
.map_err(ExecuteError::Read)?;
len += data_len;
}
RequestType::Out => {
let mut buf: Vec<u8> = Vec::new();
mem.write_all_volatile_to(*data_addr, &mut buf, *data_len as usize)
mem.write_all_to(*data_addr, disk, *data_len as usize)
.map_err(ExecuteError::Write)?;
disk.write_all(&buf).map_err(ExecuteError::WriteAll)?;
if !self.writeback {
disk.flush().map_err(ExecuteError::Flush)?;
}

View File

@@ -13,7 +13,7 @@ byteorder = "1.4.3"
event_monitor = { path = "../event_monitor" }
hypervisor = { path = "../hypervisor" }
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
pci = { path = "../pci" }
thiserror = "1.0.40"
tpm = { path = "../tpm" }
@@ -21,7 +21,7 @@ versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = "0.13.1"
vm-memory = "0.12.2"
vm-migration = { path = "../vm-migration" }
vmm-sys-util = "0.11.0"

View File

@@ -181,9 +181,8 @@ impl PciDevice for PvPanicDevice {
fn allocate_bars(
&mut self,
_allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
allocator: &Arc<Mutex<SystemAllocator>>,
_mmio_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new();
@@ -191,8 +190,10 @@ impl PciDevice for PvPanicDevice {
let bar_id = 0;
let region_size = PVPANIC_DEVICE_MMIO_SIZE;
let restoring = resources.is_some();
let bar_addr = mmio32_allocator
.allocate(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
let bar_addr = allocator
.lock()
.unwrap()
.allocate_mmio_hole_addresses(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
let bar = PciBarConfiguration::default()
@@ -217,12 +218,11 @@ impl PciDevice for PvPanicDevice {
fn free_bars(
&mut self,
_allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
allocator: &mut SystemAllocator,
_mmio_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) {
mmio32_allocator.free(GuestAddress(bar.addr()), bar.size());
allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size());
}
Ok(())

View File

@@ -36,5 +36,3 @@ You can run a SEV-SNP VM using the following command:
--memory size=1G \
--disk path=ubuntu.img
```
For more information related to Microsoft Hypervisor please see [mshv.md](mshv.md)

View File

@@ -1,48 +0,0 @@
# Microsoft Hypervisor
The Microsoft Hypervisor is a Type 1 hypervisor which runs on x64 and ARM64 architectures. As the foundation of the Hyper-V virtualization stack, it runs millions of Linux and Windows guests in Azure and on-premises deployments. It supports nested virtualization, and security features like AMD's SEV-SNP. It also supports various features in Windows such as [Device guard and confidential guard](https://techcommunity.microsoft.com/t5/iis-support-blog/windows-10-device-guard-and-credential-guard-demystified/ba-p/376419), and [WSL2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-faq)
Since 2020, Microsoft has been releasing open-source components to support Linux running as root partition on the Microsoft Hypervisor.
1. Kernel patches to support Linux booting as root partition
2. A Linux kernel driver exposing an IOCTL interface for managing guest partitions, via a device node - /dev/mshv
3. Rust bindings and IOCTL wrappers
4. IGVM related crates
## Components
The following components are related to MSHV support with Cloud-Hypervisor:
* [igvm-crates](https://github.com/microsoft/igvm) : Parsing IGVM file
* [mshv-crates](https://github.com/rust-vmm/mshv) : Rust crates to interact with kernel module (/dev/mshv)
* [igvm-tooling](https://github.com/microsoft/igvm-tooling) : Tool to generate IGVM file
## IGVM
Independent Guest Virtual Machine (IGVM) file format.The format specification can be found in the igvm_defs crate, with a Rust implementation of the binary format in the igvm crate.
The IGVM file format is designed to encapsulate all information required to launch a virtual machine on any given virtualization stack, with support for different isolation technologies such as AMD SEV-SNP and Intel TDX.
At a conceptual level, this file format is a set of commands created by the tool that generated the file, used by the loader to construct the initial guest state. The file format also contains measurement information that the underlying platform will use to confirm that the file was loaded correctly and signed by the appropriate authorities.
Cloud Hypervisor can be built using igvm feature flag along with mshv and/or sev-snp. IGVM only works with MSHV.
## SEV-SNP
AMD's [Secure Encrypted Virtualization (SEV)](https://www.amd.com/en/developer/sev.html) and extensions such as Secure Nested Paging (SEV-SNP) encrypt memory and restrict access to a guest VM's memory and registers, securing it against a compromised hypervisor or VMM. They utilize the Platform Security Processor (PSP) to store keys and encrypt/decrypt the data. Microsoft has been continuously adding/improving support for SEV-SNP on Microsoft Hyper-V. Cloud-Hypervisor can be built with the sev_snp feature including mshv and igvm feature.
## Use Cases
Cloud Hypervisor can be built to run on an MSHV root partition by enabling the mshv feature, e.g.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features mshv```
Cloud Hypervisor on MSHV can boot Linux guests using an IGVM file. IGVM feature depends on mshv for running legacy VMs.e.g.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features igvm```
For running confidential VMs on mshv, you will only need to enable sev_snp, it requires and enables mshv and igvm automatically, eg.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features sev_snp```

View File

@@ -49,7 +49,7 @@ qemu-system-x86_64 \
-m 4G \
-bios ./$OVMF_DIR/OVMF_CODE.fd \
-cdrom ./$WIN_ISO_FILE \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom
-drive if=none,id=root,file=./$IMG_FILE \
-device virtio-blk-pci,drive=root,disable-legacy=on \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \

166
fuzz/Cargo.lock generated
View File

@@ -12,9 +12,9 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.5"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -32,27 +32,27 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys",
@@ -73,9 +73,9 @@ dependencies = [
[[package]]
name = "arbitrary"
version = "1.3.2"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
checksum = "a2e1373abdaa212b704512ec2bd8b26bd0b7d5c3f70117411a5d9a451383c859"
[[package]]
name = "arc-swap"
@@ -184,18 +184,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.4.11"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.4.11"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
dependencies = [
"anstream",
"anstyle",
@@ -211,7 +211,7 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "cloud-hypervisor"
version = "36.0.0"
version = "35.0.0"
dependencies = [
"anyhow",
"api_client",
@@ -392,15 +392,15 @@ checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-sink"
version = "0.3.29"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "getrandom"
version = "0.2.11"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"js-sys",
@@ -460,9 +460,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.66"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"wasm-bindgen",
]
@@ -490,9 +490,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.150"
version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "libfuzzer-sys"
@@ -507,9 +507,9 @@ dependencies = [
[[package]]
name = "linux-loader"
version = "0.10.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "132a531b85b3a164012ab682c72f8f2cce7757f187be5f60782fd2b4cda9cb34"
checksum = "1db6a725c8000971f83fa93ed7ee1b600e55a1471a2a653379d3c84f72effdcf"
dependencies = [
"vm-memory",
]
@@ -578,9 +578,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.19.0"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "option_parser"
@@ -631,9 +631,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.70"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
@@ -678,9 +678,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.16"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "scopeguard"
@@ -705,18 +705,18 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "serde"
version = "1.0.193"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [
"proc-macro2",
"quote",
@@ -781,9 +781,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.11.2"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "spin"
@@ -880,9 +880,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.6.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
dependencies = [
"getrandom",
]
@@ -917,7 +917,7 @@ dependencies = [
[[package]]
name = "vfio-bindings"
version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#59c604fa6e42080f0a47c124ba29454fe4cb7475"
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [
"vmm-sys-util",
]
@@ -925,7 +925,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#59c604fa6e42080f0a47c124ba29454fe4cb7475"
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [
"byteorder",
"kvm-bindings",
@@ -941,7 +941,7 @@ dependencies = [
[[package]]
name = "vfio_user"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#6c72e997e61d9e84b8ee691ad63ece6c717cf5aa"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#2d96b90a7279547356ad8f83aaa3115ad5497302"
dependencies = [
"bitflags 1.3.2",
"libc",
@@ -957,11 +957,11 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.9.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "289adfce099c71f8310f895932ccd978f352ca494ea47496dbe20d4241888b82"
checksum = "61957aeb36daf0b00b87fff9c10dd28a161bd35ab157553d340d183b3d8756e6"
dependencies = [
"bitflags 2.4.1",
"bitflags 1.3.2",
"libc",
"vm-memory",
"vmm-sys-util",
@@ -969,9 +969,9 @@ dependencies = [
[[package]]
name = "virtio-bindings"
version = "0.2.2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "878bcb1b2812a10c30d53b0ed054999de3d98f25ece91fc173973f9c57aaae86"
checksum = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98"
[[package]]
name = "virtio-devices"
@@ -1009,9 +1009,9 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.10.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73a01db2cfb6c4b9bc20608b1336263d16714ea8db05de9fec2a254e076f9385"
checksum = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f"
dependencies = [
"log",
"virtio-bindings",
@@ -1048,9 +1048,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927
[[package]]
name = "vm-memory"
version = "0.13.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5376c9ee5ebe2103a310d8241936cfb93c946734b0479a4fa5bdf7a64abbacd8"
checksum = "9dc276f0d00c17b9aeb584da0f1e1c673df0d183cc2539e3636ec8cbc5eae99b"
dependencies = [
"arc-swap",
"libc",
@@ -1148,9 +1148,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.89"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1158,9 +1158,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.89"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
@@ -1173,9 +1173,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.89"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1183,9 +1183,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.89"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
@@ -1196,9 +1196,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.89"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "winapi"
@@ -1224,18 +1224,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
@@ -1248,51 +1248,51 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "zerocopy"
version = "0.7.29"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d075cf85bbb114e933343e087b92f2146bac0d55b534cbb8188becf0039948e"
checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a"
dependencies = [
"byteorder",
"zerocopy-derive",
@@ -1300,9 +1300,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
version = "0.7.29"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86cd5ca076997b97ef09d3ad65efe811fa68c9e874cb636ccb211223a813b0c2"
checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -8,25 +8,22 @@ edition = "2021"
[package.metadata]
cargo-fuzz = true
[features]
igvm = []
[dependencies]
block = { path = "../block" }
devices = { path = "../devices" }
epoll = "4.3.1"
libc = "0.2.150"
libc = "0.2.149"
libfuzzer-sys = "0.4.7"
linux-loader = { version = "0.10.0", features = ["elf", "bzimage", "pe"] }
linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
net_util = { path = "../net_util" }
once_cell = "1.19.0"
once_cell = "1.18.0"
seccompiler = "0.4.0"
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.10.0"
virtio-queue = "0.9.0"
vmm = { path = "../vmm" }
vmm-sys-util = "0.11.2"
vm-memory = "0.13.1"
vm-memory = "0.12.2"
vm-device = { path = "../vm-device" }
vm-virtio = { path = "../vm-virtio" }

View File

@@ -23,8 +23,6 @@ fuzz_target!(|bytes| {
kernel: None,
cmdline: Some(String::from_utf8_lossy(&bytes).to_string()),
initramfs: None,
#[cfg(feature = "igvm")]
igvm: None,
};
let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) {
Ok(cmdline) => cmdline,

View File

@@ -14,10 +14,10 @@ tdx = []
[dependencies]
anyhow = "1.0.75"
byteorder = "1.4.3"
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_defs = { git = "https://github.com/microsoft/igvm", branch = "main" , package = "igvm_defs", optional = true }
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main" , package = "igvm", optional = true }
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
kvm-ioctls = { version = "0.13.0", optional = true }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
@@ -25,7 +25,7 @@ mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optio
serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_with = { version = "3.4.0", default-features = false, features = ["macros"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
thiserror = "1.0.40"

View File

@@ -95,12 +95,12 @@ pub enum HypervisorCpuError {
#[error("Failed to get Msr entries: {0}")]
GetMsrEntries(#[source] anyhow::Error),
///
/// Setting multi-processing state error
/// Setting MSR entries error
///
#[error("Failed to set MP state: {0}")]
SetMpState(#[source] anyhow::Error),
///
/// Getting multi-processing state error
/// Getting Msr entries error
///
#[error("Failed to get MP state: {0}")]
GetMpState(#[source] anyhow::Error),
@@ -267,11 +267,6 @@ pub enum HypervisorCpuError {
///
#[error("Failed to write to GPA: {0}")]
GpaWrite(#[source] anyhow::Error),
///
/// Error getting CPUID leaf
///
#[error("Failed to get CPUID entries: {0}")]
GetCpuidVales(#[source] anyhow::Error),
}
#[derive(Debug)]
@@ -482,17 +477,4 @@ pub trait Vcpu: Send + Sync {
fn set_tsc_khz(&self, _freq: u32) -> Result<()> {
Ok(())
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to retrieve cpuid leaf
///
fn get_cpuid_values(
&self,
_function: u32,
_index: u32,
_xfem: u64,
_xss: u64,
) -> Result<[u32; 4]> {
unimplemented!()
}
}

View File

@@ -356,7 +356,6 @@ impl vm::Vm for KvmVm {
.set_identity_map_address(address)
.map_err(|e| vm::HypervisorVmError::SetIdentityMapAddress(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the address of the three-page region in the VM's address space.
@@ -366,7 +365,6 @@ impl vm::Vm for KvmVm {
.set_tss_address(offset)
.map_err(|e| vm::HypervisorVmError::SetTssAddress(e.into()))
}
///
/// Creates an in-kernel interrupt controller.
///
@@ -375,7 +373,6 @@ impl vm::Vm for KvmVm {
.create_irq_chip()
.map_err(|e| vm::HypervisorVmError::CreateIrq(e.into()))
}
///
/// Registers an event that will, when signaled, trigger the `gsi` IRQ.
///
@@ -384,7 +381,6 @@ impl vm::Vm for KvmVm {
.register_irqfd(fd, gsi)
.map_err(|e| vm::HypervisorVmError::RegisterIrqFd(e.into()))
}
///
/// Unregisters an event that will, when signaled, trigger the `gsi` IRQ.
///
@@ -393,7 +389,6 @@ impl vm::Vm for KvmVm {
.unregister_irqfd(fd, gsi)
.map_err(|e| vm::HypervisorVmError::UnregisterIrqFd(e.into()))
}
///
/// Creates a VcpuFd object from a vcpu RawFd.
///
@@ -416,7 +411,6 @@ impl vm::Vm for KvmVm {
};
Ok(Arc::new(vcpu))
}
#[cfg(target_arch = "aarch64")]
///
/// Creates a virtual GIC device.
@@ -426,7 +420,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {:?}", e)))?;
Ok(Arc::new(Mutex::new(gic_device)))
}
///
/// Registers an event to be signaled whenever a certain address is written to.
///
@@ -454,7 +447,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into()))
}
}
///
/// Unregisters an event from a certain address it has been previously registered to.
///
@@ -549,7 +541,6 @@ impl vm::Vm for KvmVm {
.set_gsi_routing(&irq_routing[0])
.map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into()))
}
///
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region
///
@@ -576,7 +567,6 @@ impl vm::Vm for KvmVm {
}
.into()
}
///
/// Creates a guest physical memory region.
///
@@ -613,7 +603,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::CreateUserMemory(e.into()))
}
}
///
/// Removes a guest physical memory region.
///
@@ -632,7 +621,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::RemoveUserMemory(e.into()))
}
}
///
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
///
@@ -642,7 +630,6 @@ impl vm::Vm for KvmVm {
.get_preferred_target(kvi)
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))
}
#[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> vm::Result<()> {
// Create split irqchip
@@ -658,7 +645,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?;
Ok(())
}
#[cfg(target_arch = "x86_64")]
fn enable_sgx_attribute(&self, file: File) -> vm::Result<()> {
let mut cap = kvm_enable_cap {
@@ -671,7 +657,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::EnableSgxAttribute(e.into()))?;
Ok(())
}
/// Retrieve guest clock.
#[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> {
@@ -681,7 +666,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::GetClock(e.into()))?
.into())
}
/// Set guest clock.
#[cfg(target_arch = "x86_64")]
fn set_clock(&self, data: &ClockData) -> vm::Result<()> {
@@ -690,7 +674,6 @@ impl vm::Vm for KvmVm {
.set_clock(&data)
.map_err(|e| vm::HypervisorVmError::SetClock(e.into()))
}
/// Create a device that is used for passthrough
fn create_passthrough_device(&self) -> vm::Result<VfioDeviceFd> {
let mut vfio_dev = kvm_create_device {
@@ -702,7 +685,6 @@ impl vm::Vm for KvmVm {
self.create_device(&mut vfio_dev)
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
}
///
/// Start logging dirty pages
///
@@ -844,7 +826,6 @@ impl vm::Vm for KvmVm {
)
.map_err(vm::HypervisorVmError::InitMemRegionTdx)
}
/// Downcast to the underlying KvmVm type
fn as_any(&self) -> &dyn Any {
self
@@ -911,9 +892,7 @@ pub enum KvmError {
#[error("Capability missing: {0:?}")]
CapabilityMissing(Cap),
}
pub type KvmResult<T> = result::Result<T, KvmError>;
impl KvmHypervisor {
/// Create a hypervisor based on Kvm
#[allow(clippy::new_ret_no_self)]
@@ -927,7 +906,6 @@ impl KvmHypervisor {
Ok(Arc::new(KvmHypervisor { kvm: kvm_obj }))
}
/// Check if the hypervisor is available
pub fn is_available() -> hypervisor::Result<bool> {
match std::fs::metadata("/dev/kvm") {
@@ -939,7 +917,6 @@ impl KvmHypervisor {
}
}
}
/// Implementation of Hypervisor trait for KVM
///
/// # Examples
@@ -958,7 +935,6 @@ impl hypervisor::Hypervisor for KvmHypervisor {
fn hypervisor_type(&self) -> HypervisorType {
HypervisorType::Kvm
}
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object
///
/// # Examples
@@ -1114,7 +1090,6 @@ impl hypervisor::Hypervisor for KvmHypervisor {
self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32
}
}
/// Vcpu struct for KVM
pub struct KvmVcpu {
fd: VcpuFd,
@@ -1124,7 +1099,6 @@ pub struct KvmVcpu {
#[cfg(target_arch = "x86_64")]
hyperv_synic: AtomicBool,
}
/// Implementation of Vcpu trait for KVM
///
/// # Examples
@@ -1149,7 +1123,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
.into())
}
///
/// Returns the vCPU general purpose registers.
/// The `KVM_GET_REGS` ioctl is not available on AArch64, `KVM_GET_ONE_REG`
@@ -1262,7 +1235,6 @@ impl cpu::Vcpu for KvmVcpu {
.unwrap();
Ok(state)
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the vCPU general purpose registers using the `KVM_SET_REGS` ioctl.
@@ -1385,7 +1357,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the vCPU special registers using the `KVM_SET_SREGS` ioctl.
@@ -1396,7 +1367,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_sregs(&sregs)
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the floating point state (FPU) from the vCPU.
@@ -1408,7 +1378,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct.
@@ -1419,7 +1388,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_fpu(&fpu)
.map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to setup the CPUID registers.
@@ -1434,7 +1402,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_cpuid2(&kvm_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to enable HyperV SynIC
@@ -1452,7 +1419,6 @@ impl cpu::Vcpu for KvmVcpu {
.enable_cap(&cap)
.map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into()))
}
///
/// X86 specific call to retrieve the CPUID registers.
///
@@ -1467,7 +1433,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(v)
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1479,7 +1444,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1490,7 +1454,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_lapic(&klapic)
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the model-specific registers (MSR) for this vCPU.
@@ -1512,7 +1475,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(succ)
}
#[cfg(target_arch = "x86_64")]
///
/// Setup the model-specific registers (MSR) for this vCPU.
@@ -1525,7 +1487,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_msrs(&kvm_msrs)
.map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into()))
}
///
/// Returns the vcpu's current "multiprocessing state".
///
@@ -1536,7 +1497,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))?
.into())
}
///
/// Sets the vcpu's current "multiprocessing state".
///
@@ -1545,7 +1505,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_mp_state(mp_state.into())
.map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Translates guest virtual address to guest physical address using the `KVM_TRANSLATE` ioctl.
@@ -1564,7 +1523,6 @@ impl cpu::Vcpu for KvmVcpu {
_ => Ok((tr.physical_address, 0)),
}
}
///
/// Triggers the running of the current virtual CPU returning an exit reason.
///
@@ -1656,7 +1614,6 @@ impl cpu::Vcpu for KvmVcpu {
},
}
}
#[cfg(target_arch = "x86_64")]
///
/// Let the guest know that it has been paused, which prevents from
@@ -1674,7 +1631,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(())
}
///
/// Sets debug registers to set hardware breakpoints and/or enable single step.
///
@@ -1728,14 +1684,12 @@ impl cpu::Vcpu for KvmVcpu {
.set_guest_debug(&dbg)
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))
}
#[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
self.fd
.vcpu_init(kvi)
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
}
///
/// Gets a list of the guest registers that are supported for the
/// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
@@ -1746,7 +1700,6 @@ impl cpu::Vcpu for KvmVcpu {
.get_reg_list(reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
}
///
/// Gets the value of a system register
///
@@ -1780,7 +1733,6 @@ impl cpu::Vcpu for KvmVcpu {
.try_into()
.unwrap())
}
///
/// Configure core registers for a given CPU.
///
@@ -1955,7 +1907,6 @@ impl cpu::Vcpu for KvmVcpu {
}
.into())
}
///
/// Get the current AArch64 CPU state
///
@@ -2005,7 +1956,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(state.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Restore the previously saved CPU state
@@ -2095,7 +2045,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(())
}
///
/// Restore the previously saved AArch64 CPU state
///
@@ -2170,7 +2119,6 @@ impl cpu::Vcpu for KvmVcpu {
TdxExitStatus::InvalidOperand => TDG_VP_VMCALL_INVALID_OPERAND,
};
}
#[cfg(target_arch = "x86_64")]
///
/// Return the list of initial MSR entries for a VCPU
@@ -2196,7 +2144,6 @@ impl cpu::Vcpu for KvmVcpu {
]
.to_vec()
}
#[cfg(target_arch = "aarch64")]
fn has_pmu_support(&self) -> bool {
let cpu_attr = kvm_bindings::kvm_device_attr {
@@ -2207,7 +2154,6 @@ impl cpu::Vcpu for KvmVcpu {
};
self.fd.has_device_attr(&cpu_attr).is_ok()
}
#[cfg(target_arch = "aarch64")]
fn init_pmu(&self, irq: u32) -> cpu::Result<()> {
let cpu_attr = kvm_bindings::kvm_device_attr {
@@ -2275,7 +2221,6 @@ impl KvmVcpu {
.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".
@@ -2285,7 +2230,6 @@ impl KvmVcpu {
.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".
@@ -2295,7 +2239,6 @@ impl KvmVcpu {
.get_xcrs()
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that sets the vcpu's current "xcrs".
@@ -2305,7 +2248,6 @@ impl KvmVcpu {
.set_xcrs(xcrs)
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns currently pending exceptions, interrupts, and NMIs as well as related
@@ -2316,7 +2258,6 @@ impl KvmVcpu {
.get_vcpu_events()
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Sets pending exceptions, interrupts, and NMIs as well as related states

View File

@@ -200,7 +200,6 @@ impl MshvHypervisor {
}
}
}
/// Implementation of Hypervisor trait for Mshv
///
/// # Examples
@@ -339,8 +338,6 @@ pub struct MshvVcpu {
cpuid: Vec<CpuIdEntry>,
msrs: Vec<MsrEntry>,
vm_ops: Option<Arc<dyn vm::VmOps>>,
#[cfg(feature = "sev_snp")]
vm_fd: Arc<VmFd>,
}
/// Implementation of Vcpu trait for Microsoft Hypervisor
@@ -367,7 +364,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the vCPU general purpose registers.
@@ -378,7 +374,6 @@ impl cpu::Vcpu for MshvVcpu {
.set_regs(&regs)
.map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the vCPU special registers.
@@ -390,7 +385,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the vCPU special registers.
@@ -401,7 +395,6 @@ impl cpu::Vcpu for MshvVcpu {
.set_sregs(&sregs)
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the floating point state (FPU) from the vCPU.
@@ -413,7 +406,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Set the floating point state (FPU) of a vCPU.
@@ -446,7 +438,6 @@ impl cpu::Vcpu for MshvVcpu {
Ok(succ)
}
#[cfg(target_arch = "x86_64")]
///
/// Setup the model-specific registers (MSR) for this vCPU.
@@ -468,7 +459,6 @@ impl cpu::Vcpu for MshvVcpu {
/* We always have SynIC enabled on MSHV */
Ok(())
}
#[allow(non_upper_case_globals)]
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
let hv_message: hv_message = hv_message::default();
@@ -986,59 +976,6 @@ impl cpu::Vcpu for MshvVcpu {
})?;
}
}
SVM_EXITCODE_SNP_GUEST_REQUEST => {
let req_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1;
let rsp_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info2;
let mshv_psp_req =
mshv_issue_psp_guest_request { req_gpa, rsp_gpa };
self.vm_fd
.psp_issue_guest_request(&mshv_psp_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
debug!(
"SNP guest request: req_gpa {:0x} rsp_gpa {:0x}",
req_gpa, rsp_gpa
);
let mut swei2_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO2_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei2_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
}
SVM_EXITCODE_SNP_AP_CREATION => {
let vmsa_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info2;
let apic_id =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1 >> 32;
debug!(
"SNP AP CREATE REQUEST with VMSA GPA {:0x}, and APIC ID {:?}",
vmsa_gpa, apic_id
);
let mshv_ap_create_req = mshv_sev_snp_ap_create {
vp_id: apic_id,
vmsa_gpa,
};
self.vm_fd
.sev_snp_ap_create(&mshv_ap_create_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
let mut swei2_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO2_OFFSET,
byte_count: std::mem::size_of::<u64>() as u32,
..Default::default()
};
self.fd
.gpa_write(&mut swei2_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
}
_ => panic!(
"GHCB_INFO_NORMAL: Unhandled exit code: {:0x}",
exit_code
@@ -1065,7 +1002,6 @@ impl cpu::Vcpu for MshvVcpu {
},
}
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to setup the CPUID registers.
@@ -1079,7 +1015,6 @@ impl cpu::Vcpu for MshvVcpu {
.register_intercept_result_cpuid(&mshv_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to retrieve the CPUID registers.
@@ -1087,23 +1022,6 @@ impl cpu::Vcpu for MshvVcpu {
fn get_cpuid2(&self, _num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> {
Ok(self.cpuid.clone())
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to retrieve cpuid leaf
///
fn get_cpuid_values(
&self,
function: u32,
index: u32,
xfem: u64,
xss: u64,
) -> cpu::Result<[u32; 4]> {
self.fd
.get_cpuid_values(function, index, xfem, xss)
.map_err(|e| cpu::HypervisorCpuError::GetCpuidVales(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1115,7 +1033,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1126,21 +1043,18 @@ impl cpu::Vcpu for MshvVcpu {
.set_lapic(&lapic)
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
}
///
/// Returns the vcpu's current "multiprocessing state".
///
fn get_mp_state(&self) -> cpu::Result<MpState> {
Ok(MpState::Mshv)
}
///
/// Sets the vcpu's current "multiprocessing state".
///
fn set_mp_state(&self, _mp_state: MpState) -> cpu::Result<()> {
Ok(())
}
///
/// Set CPU state
///
@@ -1166,7 +1080,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
Ok(())
}
///
/// Get CPU State
///
@@ -1203,7 +1116,6 @@ impl cpu::Vcpu for MshvVcpu {
}
.into())
}
#[cfg(target_arch = "x86_64")]
///
/// Translate guest virtual address to guest physical address
@@ -1220,7 +1132,6 @@ impl cpu::Vcpu for MshvVcpu {
Ok((gpa, result_code))
}
#[cfg(target_arch = "x86_64")]
///
/// Return the list of initial MSR entries for a VCPU
@@ -1253,7 +1164,6 @@ impl MshvVcpu {
.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".
@@ -1263,7 +1173,6 @@ impl MshvVcpu {
.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".
@@ -1273,7 +1182,6 @@ impl MshvVcpu {
.get_xcrs()
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call that sets the vcpu's current "xcrs".
@@ -1283,7 +1191,6 @@ impl MshvVcpu {
.set_xcrs(xcrs)
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Returns currently pending exceptions, interrupts, and NMIs as well as related
@@ -1294,7 +1201,6 @@ impl MshvVcpu {
.get_vcpu_events()
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Sets pending exceptions, interrupts, and NMIs as well as related states
@@ -1474,7 +1380,6 @@ impl vm::Vm for MshvVm {
fn set_identity_map_address(&self, _address: u64) -> vm::Result<()> {
Ok(())
}
#[cfg(target_arch = "x86_64")]
///
/// Sets the address of the three-page region in the VM's address space.
@@ -1482,14 +1387,12 @@ impl vm::Vm for MshvVm {
fn set_tss_address(&self, _offset: usize) -> vm::Result<()> {
Ok(())
}
///
/// Creates an in-kernel interrupt controller.
///
fn create_irq_chip(&self) -> vm::Result<()> {
Ok(())
}
///
/// Registers an event that will, when signaled, trigger the `gsi` IRQ.
///
@@ -1502,7 +1405,6 @@ impl vm::Vm for MshvVm {
Ok(())
}
///
/// Unregisters an event that will, when signaled, trigger the `gsi` IRQ.
///
@@ -1515,7 +1417,6 @@ impl vm::Vm for MshvVm {
Ok(())
}
///
/// Creates a VcpuFd object from a vcpu RawFd.
///
@@ -1534,22 +1435,17 @@ impl vm::Vm for MshvVm {
cpuid: Vec::new(),
msrs: self.msrs.clone(),
vm_ops,
#[cfg(feature = "sev_snp")]
vm_fd: self.fd.clone(),
};
Ok(Arc::new(vcpu))
}
#[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> vm::Result<()> {
Ok(())
}
#[cfg(target_arch = "x86_64")]
fn enable_sgx_attribute(&self, _file: File) -> vm::Result<()> {
Ok(())
}
fn register_ioevent(
&self,
fd: &EventFd,
@@ -1580,7 +1476,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into()))
}
}
/// Unregister an event from a certain address it has been previously registered to.
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> {
let addr = &mshv_ioctls::IoEventAddress::from(*addr);
@@ -1705,7 +1600,6 @@ impl vm::Vm for MshvVm {
.set_msi_routing(&msi_routing[0])
.map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into()))
}
///
/// Start logging dirty pages
///
@@ -1714,7 +1608,6 @@ impl vm::Vm for MshvVm {
.enable_dirty_page_tracking()
.map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))
}
///
/// Stop logging dirty pages
///
@@ -1733,7 +1626,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?;
Ok(())
}
///
/// Get dirty pages bitmap (one bit per page)
///
@@ -1746,24 +1638,20 @@ impl vm::Vm for MshvVm {
)
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
}
/// Retrieve guest clock.
#[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> {
Ok(ClockData::Mshv)
}
/// Set guest clock.
#[cfg(target_arch = "x86_64")]
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
Ok(())
}
/// Downcast to the underlying MshvVm type
fn as_any(&self) -> &dyn Any {
self
}
/// Initialize the SEV-SNP VM
#[cfg(feature = "sev_snp")]
fn sev_snp_init(&self) -> vm::Result<()> {
@@ -1775,9 +1663,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::InitializeSevSnp(e.into()))
}
///
/// Importing isolated pages, these pages will be used
/// for the PSP(Platform Security Processor) measurement.
#[cfg(feature = "sev_snp")]
fn import_isolated_pages(
&self,
@@ -1805,11 +1690,6 @@ impl vm::Vm for MshvVm {
.import_isolated_pages(&isolated_pages[0])
.map_err(|e| vm::HypervisorVmError::ImportIsolatedPages(e.into()))
}
///
/// Complete isolated import, telling the hypervisor that
/// importing the pages to guest memory is complete.
///
#[cfg(feature = "sev_snp")]
fn complete_isolated_import(
&self,

View File

@@ -8,7 +8,7 @@ edition = "2021"
epoll = "4.3.3"
getrandom = "0.2.10"
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = "1.0.168"
@@ -16,8 +16,8 @@ thiserror = "1.0.40"
versionize = "0.1.10"
versionize_derive = "0.1.4"
virtio-bindings = "0.2.0"
virtio-queue = "0.10.0"
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
virtio-queue = "0.9.0"
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.11.0"

View File

@@ -72,10 +72,6 @@ pub fn open_tap(
let mut taps: Vec<Tap> = Vec::new();
let mut ifname: String = String::new();
let vnet_hdr_size = vnet_hdr_len() as i32;
// Check if the given interface exists before we create it.
let tap_existed = if_name.map_or(false, |n| {
Path::new(&format!("/sys/class/net/{n}")).exists()
});
// In case the tap interface already exists, check if the number of
// queues is appropriate. The tap might not support multiqueue while
@@ -91,19 +87,11 @@ pub fn open_tap(
Some(name) => Tap::open_named(name, num_rx_q, flags).map_err(Error::TapOpen)?,
None => Tap::new(num_rx_q).map_err(Error::TapOpen)?,
};
// Don't overwrite ip configuration of existing interfaces:
if !tap_existed {
if let Some(ip) = ip_addr {
tap.set_ip_addr(ip).map_err(Error::TapSetIp)?;
}
if let Some(mask) = netmask {
tap.set_netmask(mask).map_err(Error::TapSetNetmask)?;
}
} else {
warn!(
"Tap {} already exists. IP configuration will not be overwritten.",
if_name.unwrap_or_default()
);
if let Some(ip) = ip_addr {
tap.set_ip_addr(ip).map_err(Error::TapSetIp)?;
}
if let Some(mask) = netmask {
tap.set_netmask(mask).map_err(Error::TapSetNetmask)?;
}
if let Some(mac) = host_mac {
tap.set_mac_addr(*mac).map_err(Error::TapSetMac)?

View File

@@ -19,12 +19,12 @@ vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
vmm-sys-util = "0.11.0"
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
serde = { version = "1.0.168", features = ["derive"] }
thiserror = "1.0.40"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }

View File

@@ -58,8 +58,7 @@ pub trait PciDevice: BusDevice {
fn allocate_bars(
&mut self,
_allocator: &Arc<Mutex<SystemAllocator>>,
_mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
_mmio_allocator: &mut AddressAllocator,
_resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>> {
Ok(Vec::new())
@@ -69,8 +68,7 @@ pub trait PciDevice: BusDevice {
fn free_bars(
&mut self,
_allocator: &mut SystemAllocator,
_mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
_mmio_allocator: &mut AddressAllocator,
) -> Result<()> {
Ok(())
}

View File

@@ -529,13 +529,10 @@ impl VfioCommon {
}
}
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn allocate_bars(
&mut self,
allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new();
@@ -684,15 +681,21 @@ impl VfioCommon {
}
PciBarRegionType::Memory32BitRegion => {
// BAR allocation must be naturally aligned
mmio32_allocator
.allocate(restored_bar_addr, region_size, Some(region_size))
allocator
.lock()
.unwrap()
.allocate_mmio_hole_addresses(
restored_bar_addr,
region_size,
Some(region_size),
)
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
}
PciBarRegionType::Memory64BitRegion => {
// We need do some fixup to keep MMIO RW region and msix cap region page size
// aligned.
region_size = self.fixup_msix_region(bar_id, region_size);
mmio64_allocator
mmio_allocator
.allocate(
restored_bar_addr,
region_size,
@@ -739,13 +742,10 @@ impl VfioCommon {
Ok(bars)
}
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn free_bars(
&mut self,
allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> {
for region in self.mmio_regions.iter() {
match region.type_ {
@@ -756,10 +756,10 @@ impl VfioCommon {
error!("I/O region is not supported");
}
PciBarRegionType::Memory32BitRegion => {
mmio32_allocator.free(region.start, region.length);
allocator.free_mmio_hole_addresses(region.start, region.length);
}
PciBarRegionType::Memory64BitRegion => {
mmio64_allocator.free(region.start, region.length);
mmio_allocator.free(region.start, region.length);
}
}
}
@@ -1694,22 +1694,19 @@ impl PciDevice for VfioPciDevice {
fn allocate_bars(
&mut self,
allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common
.allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources)
.allocate_bars(allocator, mmio_allocator, resources)
}
fn free_bars(
&mut self,
allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> {
self.common
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
self.common.free_bars(allocator, mmio_allocator)
}
fn write_config_register(

View File

@@ -397,22 +397,19 @@ impl PciDevice for VfioUserPciDevice {
fn allocate_bars(
&mut self,
allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common
.allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources)
.allocate_bars(allocator, mmio_allocator, resources)
}
fn free_bars(
&mut self,
allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
mmio_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> {
self.common
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
self.common.free_bars(allocator, mmio_allocator)
}
fn as_any(&mut self) -> &mut dyn Any {

View File

@@ -6,7 +6,7 @@ edition = "2021"
build = "../build.rs"
[dependencies]
clap = { version = "4.4.7", features = ["wrap_help"] }
clap = { version = "4.0.32", features = ["wrap_help"] }
dirs = "5.0.0"
serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107"

View File

@@ -5,5 +5,5 @@ edition = "2021"
[dependencies]
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
vmm-sys-util = "0.11.0"

View File

@@ -1,11 +1,4 @@
- [v37.0](#v370)
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [Improved VFIO Device Passthrough with Multiple PCI Segments](#improved-vfio-device-passthrough-with-multiple-pci-segments)
- [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)
- [Contributors](#contributors)
- [v36.1](#v361)
- [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)
@@ -14,31 +7,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-1)
- [Contributors](#contributors-1)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [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-2)
- [Contributors](#contributors-2)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [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-3)
- [Contributors](#contributors-3)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-2)
- [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-4)
- [Contributors](#contributors-4)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-3)
- [v32.0](#v320)
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
- [API Changes](#api-changes)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-4)
- [v31.1](#v311)
- [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
@@ -46,15 +39,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-6)
- [Contributors](#contributors-6)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-5)
- [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-7)
- [Contributors](#contributors-7)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-6)
- [v28.2](#v282)
- [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
@@ -64,20 +57,20 @@
- [`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-8)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Removals](#removals)
- [Deprecations](#deprecations)
- [Contributors](#contributors-8)
- [Contributors](#contributors-7)
- [v28.1](#v281)
- [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder)
- [Long Term Support (LTS) Release](#long-term-support-lts-release-1)
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [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-9)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Removals](#removals-1)
- [Contributors](#contributors-9)
- [Contributors](#contributors-8)
- [v27.0](#v270)
- [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages)
@@ -86,41 +79,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-10)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-10)
- [Contributors](#contributors-9)
- [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-11)
- [Notable Bug Fixes](#notable-bug-fixes-10)
- [Deprecations](#deprecations-2)
- [Removals](#removals-2)
- [Contributors](#contributors-11)
- [Contributors](#contributors-10)
- [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Notable Bug Fixes](#notable-bug-fixes-11)
- [Removals](#removals-3)
- [Contributors](#contributors-12)
- [Contributors](#contributors-11)
- [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-13)
- [Notable Bug Fixes](#notable-bug-fixes-12)
- [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website)
- [Contributors](#contributors-13)
- [Contributors](#contributors-12)
- [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-14)
- [Notable Bug Fixes](#notable-bug-fixes-13)
- [Deprecations](#deprecations-4)
- [Contributors](#contributors-14)
- [Contributors](#contributors-13)
- [v22.1](#v221)
- [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support)
@@ -131,13 +124,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-15)
- [Contributors](#contributors-15)
- [Notable Bug Fixes](#notable-bug-fixes-14)
- [Contributors](#contributors-14)
- [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-16)
- [Contributors](#contributors-16)
- [Notable Bug fixes](#notable-bug-fixes-15)
- [Contributors](#contributors-15)
- [v20.2](#v202)
- [v20.1](#v201)
- [v20.0](#v200)
@@ -146,8 +139,8 @@
- [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code)
- [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-17)
- [Notable bug fixes](#notable-bug-fixes-16)
- [Contributors](#contributors-16)
- [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)
@@ -155,8 +148,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-18)
- [Contributors](#contributors-18)
- [Notable bug fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-17)
- [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)
@@ -166,23 +159,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-19)
- [Contributors](#contributors-19)
- [Notable bug fixes](#notable-bug-fixes-18)
- [Contributors](#contributors-18)
- [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-20)
- [Contributors](#contributors-20)
- [Notable bug fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-19)
- [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-21)
- [Notable bug fixes](#notable-bug-fixes-20)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors-21)
- [Contributors](#contributors-20)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@@ -190,7 +183,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5)
- [Contributors](#contributors-22)
- [Contributors](#contributors-21)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@@ -200,7 +193,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-23)
- [Contributors](#contributors-22)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@@ -208,13 +201,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-24)
- [Contributors](#contributors-23)
- [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-25)
- [Contributors](#contributors-24)
- [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)
@@ -226,15 +219,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-22)
- [Contributors](#contributors-26)
- [Notable Bug Fixes](#notable-bug-fixes-21)
- [Contributors](#contributors-25)
- [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-23)
- [Contributors](#contributors-27)
- [Notable Bug Fixes](#notable-bug-fixes-22)
- [Contributors](#contributors-26)
- [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)
@@ -247,17 +240,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-24)
- [Contributors](#contributors-28)
- [Notable Bug Fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-27)
- [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-25)
- [Notable Bug Fixes](#notable-bug-fixes-24)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-29)
- [Contributors](#contributors-28)
- [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)
@@ -267,14 +260,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-30)
- [Contributors](#contributors-29)
- [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-31)
- [Contributors](#contributors-30)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -282,7 +275,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-32)
- [Contributors](#contributors-31)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -291,7 +284,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-33)
- [Contributors](#contributors-32)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@@ -318,68 +311,16 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# v37.0
# v36.1
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v37.0. The following user visible changes have been made:
### Long Term Support (LTS) Release
This release is a LTS release. Point releases for bug fixes will be made
for the next 18 months; live migration and live upgrade will be
supported between the point releases of the LTS.
### Multiple PCI segments Support for 32-bit VFIO devices
Now VFIO devices with 32-bit memory BARs can be attached to non-zero PCI
segments on the guest, allowing users to have more 32-bit devices and
assign such devices to appropriate NUMA nodes for better performance.
### Configurable Named TAP Devices
Named TAP devices now accepts IP configuration from users, such as IP
and MAC address, as long as the named TAP device is created by Cloud
Hypervisor (e.g. not existing TAP devices).
### TTY Output from Both Serial Device and Virtio Console
Now legacy serial device and virtio console can be set as TTY mode as
the same time. This allows users to capture early boot logs with the
legacy serial device without losing performance benefits of using
virtio-console, when appropriate kernel configuration is used (such as
using kernel command-line `console=hvc0 earlyprintk=ttyS0` on x86).
### Faster VM Restoration from Snapshots
The speed of VM restoration from snapshots is improved with a better
implementation of deserializing JSON files.
### Notable Bug Fixes
This is a bug fix release. The following issues have been addressed:
* Fix aio backend behavior for block devices when writeback cache
disabled (#5930)
disabled (#5930)
* Fix PvPanic device PCI BAR alignment (#5956)
* Bug fix to OpenAPI specification file (#5967)
* Error out early for live migration when TDX is enabled (#6025)
### Contributors
Many thanks to everyone who has contributed to our release:
* Bo Chen <chen.bo@intel.com>
* Jinank Jain <jinankjain@microsoft.com>
* Markus Sütter <markus.suetter@secunet.com>
* Michael Zhao <michael.zhao@arm.com>
* Muminul Islam <muislam@microsoft.com>
* Rob Bradford <rbradford@rivosinc.com>
* Rui Chang <rui.chang@arm.com>
* Ruslan Mstoi <ruslan.mstoi@intel.com>
* Thomas Barrett <tbarrett@crusoeenergy.com>
* Wei Liu <liuwe@microsoft.com>
* Yi Wang <foxywang@tencent.com>
* Yong He <alexyonghe@tencent.com>
# v36.0
This release has been tracked in our [roadmap

View File

@@ -3,10 +3,10 @@
# When changing this file don't forget to update the tag name in the
# .github/workflows/docker-image.yaml file if doing multiple per day
FROM ubuntu:20.04 as dev
FROM ubuntu:22.04 as dev
ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.70.0"
ARG RUST_TOOLCHAIN="1.67.1"
ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
@@ -43,7 +43,6 @@ RUN apt-get update \
socat \
dosfstools \
cpio \
python \
python3 \
python3-setuptools \
ntfs-3g \

View File

@@ -7,7 +7,7 @@
CLI_NAME="Cloud Hypervisor"
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
CTR_IMAGE_VERSION="20231108-0"
CTR_IMAGE_VERSION="20231220-0"
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
DOCKER_RUNTIME="docker"
@@ -285,8 +285,7 @@ cmd_build() {
rustflags="$RUSTFLAGS"
target_cc=""
if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then
rustflags="$rustflags -C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
target_cc="musl-gcc"
rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc"
fi
$DOCKER_RUNTIME run \
@@ -399,8 +398,7 @@ cmd_tests() {
rustflags="$RUSTFLAGS"
target_cc=""
if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then
rustflags="$rustflags -C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
target_cc="musl-gcc"
rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc"
fi
if [[ "$unit" = true ]]; then
@@ -436,7 +434,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -458,7 +455,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -480,7 +476,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -502,7 +497,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -524,7 +518,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -546,7 +539,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $?
fi
@@ -569,7 +561,6 @@ cmd_tests() {
--env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
fi

View File

@@ -1,91 +0,0 @@
from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle
import re
class TitleStartsWithComponent(LineRule):
"""A rule to enforce valid commit message title
Valid title format:
component1[, component2, componentN]: submodule: summary
Title should have at least one component
Components are separated by comma+space: ", "
Components are validated to be in valid_components
Components list is ended by a colon
Submodules are not validated
"""
# A rule MUST have a human friendly name
name = "title-has-valid-component"
# A rule MUST have a *unique* id.
# We recommend starting with UL (for User-defined Line-rule)
id = "UL1"
# A line-rule MUST have a target (not required for CommitRules).
target = CommitMessageTitle
def validate(self, line, _commit):
valid_components = (
'api_client',
'arch',
'block',
'build',
'ch-remote',
'ci',
'devices',
'docs',
'event_monitor',
'fuzz',
'github',
'gitignore',
'gitlint',
'hypervisor',
'Jenkinsfile',
'misc',
'net_gen',
'net_util',
'option_parser',
'pci',
'performance-metrics',
'rate_limiter',
'README',
'resources',
'scripts',
'serial_buffer',
'test_data',
'test_infra',
'tests',
'tpm',
'tracer',
'vhost_user_block',
'vhost_user_net',
'virtio-devices',
'vm-allocator',
'vm-device',
'vmm',
'vm-migration',
'vm-virtio')
ptrn_title = re.compile(r'^(.+?):\s(.+)$')
match = ptrn_title.match(line)
if not match:
self.log.debug("Invalid commit title {}", line)
return [RuleViolation(self.id, "Commit title does not comply with "
"rule: 'component: change summary'")]
components = match.group(1)
summary = match.group(2)
self.log.debug(f"\nComponents: {components}\nSummary: {summary}")
ptrn_components = re.compile(r',\s')
components_list = re.split(ptrn_components, components)
self.log.debug("components list: %s" % components_list)
for component in components_list:
if component not in valid_components:
return [RuleViolation(self.id,
f"Invalid component: {component}, "
"\nValid components are: {}".format(
" ".join(valid_components)))]

View File

@@ -20,7 +20,7 @@ build_spdk_nvme() {
sed -i "/grpcio/d" scripts/pkgdep/debian.sh
./scripts/pkgdep.sh
./configure --with-vfio-user
chmod +x /usr/local/lib/python3.8/dist-packages/ninja/data/bin/ninja
chmod +x /usr/local/lib/python3.10/dist-packages/ninja/data/bin/ninja
make -j `nproc` || exit 1
touch .built
popd
@@ -30,7 +30,7 @@ build_spdk_nvme() {
fi
cp "$WORKLOADS_DIR/spdk/build/bin/nvmf_tgt" $SPDK_DEPLOY_DIR/nvmf_tgt
cp "$WORKLOADS_DIR/spdk/scripts/rpc.py" $SPDK_DEPLOY_DIR/rpc.py
cp -r "$WORKLOADS_DIR/spdk/scripts/rpc" $SPDK_DEPLOY_DIR/rpc
cp -r "$WORKLOADS_DIR/spdk/python/spdk/" $SPDK_DEPLOY_DIR/
cp -r "$WORKLOADS_DIR/spdk/python" $SPDK_DEPLOY_DIR/../
}
@@ -38,7 +38,7 @@ build_virtiofsd() {
VIRTIOFSD_DIR="$WORKLOADS_DIR/virtiofsd_build"
VIRTIOFSD_REPO="https://gitlab.com/virtio-fs/virtiofsd.git"
checkout_repo "$VIRTIOFSD_DIR" "$VIRTIOFSD_REPO" v1.1.0 "220405d7a2606c92636d31992b5cb3036a41047b"
checkout_repo "$VIRTIOFSD_DIR" "$VIRTIOFSD_REPO" v1.8.0 "97ea7908fe7f9bc59916671a771bdcfaf4044b45"
if [ ! -f "$VIRTIOFSD_DIR/.built" ]; then
pushd $VIRTIOFSD_DIR

View File

@@ -14,7 +14,12 @@ fi
WORKLOADS_DIR="$HOME/workloads"
mkdir -p "$WORKLOADS_DIR"
download_hypervisor_fw
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
FW="$WORKLOADS_DIR/hypervisor-fw"
pushd $WORKLOADS_DIR
rm -f $FW
time wget --quiet $FW_URL || exit 1
popd
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"

View File

@@ -14,7 +14,11 @@ process_common_args "$@"
WORKLOADS_DIR="$HOME/workloads"
download_hypervisor_fw
# Always download the latest "hypervisor-fw"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
pushd $WORKLOADS_DIR
time wget --quiet $FW_URL -O hypervisor-fw || exit 1
popd
CFLAGS=""
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then

View File

@@ -18,7 +18,13 @@ fi
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
download_hypervisor_fw
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
FW="$WORKLOADS_DIR/hypervisor-fw"
if [ ! -f "$FW" ]; then
pushd $WORKLOADS_DIR
time wget --quiet $FW_URL || exit 1
popd
fi
OVMF_FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/edk2/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
OVMF_FW="$WORKLOADS_DIR/CLOUDHV.fd"
@@ -116,7 +122,7 @@ if [ ! -f "$VIRTIOFSD" ]; then
pushd $WORKLOADS_DIR
git clone "https://gitlab.com/virtio-fs/virtiofsd.git" $VIRTIOFSD_DIR
pushd $VIRTIOFSD_DIR
git checkout v1.1.0
git checkout v1.8.0
time cargo build --release
cp target/release/virtiofsd $VIRTIOFSD || exit 1
popd

View File

@@ -107,20 +107,3 @@ process_common_args() {
test_binary_args=($@)
}
download_hypervisor_fw() {
if [ -n "$AUTH_DOWNLOAD_TOKEN" ]; then
echo "Using authenticated download from GitHub"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest \
--header "Authorization: Token $AUTH_DOWNLOAD_TOKEN" \
--header "X-GitHub-Api-Version: 2022-11-28" | grep "browser_download_url" | grep -o 'https://.*[^ "]')
else
echo "Using anonymous download from GitHub"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
fi
FW="$WORKLOADS_DIR/hypervisor-fw"
pushd $WORKLOADS_DIR
rm -f $FW
time wget --quiet $FW_URL || exit 1
popd
}

View File

@@ -443,14 +443,7 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.num_args(0)
.group("vmm-config"),
);
#[cfg(feature = "igvm")]
let app = app.arg(
Arg::new("igvm")
.long("igvm")
.help("Path to IGVM file to load.")
.num_args(1)
.group("vm-config"),
);
app.arg(
Arg::new("version")
.short('V')

View File

@@ -90,7 +90,7 @@ impl GuestNetworkConfig {
None => DEFAULT_TCP_LISTENER_TIMEOUT,
};
match (|| -> Result<(), WaitForBootError> {
let mut closure = || -> Result<(), WaitForBootError> {
let listener =
TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
listener
@@ -143,17 +143,19 @@ impl GuestNetworkConfig {
Err(WaitForBootError::Accept(e))
}
}
})() {
};
match closure() {
Err(e) => {
let duration = start.elapsed();
eprintln!(
"\n\n==== Start 'wait_vm_boot' (FAILED) ==== \
\n\nduration =\"{duration:?}, timeout = {timeout}s\" \
\nlisten_addr=\"{listen_addr}\" \
\nexpected_guest_addr=\"{expected_guest_addr}\" \
\nmessage=\"{s}\" \
\nerror=\"{e:?}\" \
\n\n==== End 'wait_vm_boot' outout ====\n\n"
"\n\n==== Start 'wait_vm_boot' (FAILED) ====\n\n\
duration =\"{duration:?}, timeout = {timeout}s\"\n\
listen_addr=\"{listen_addr}\"\n\
expected_guest_addr=\"{expected_guest_addr}\"\n\
message=\"{s}\"\n\
error=\"{e:?}\"\n\
\n==== End 'wait_vm_boot' outout ====\n\n"
);
Err(e)
@@ -559,7 +561,7 @@ fn scp_to_guest_with_auth(
) -> Result<(), SshCommandError> {
let mut counter = 0;
loop {
match (|| -> Result<(), SshCommandError> {
let closure = || -> Result<(), SshCommandError> {
let tcp =
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
let mut sess = Session::new().unwrap();
@@ -592,7 +594,9 @@ fn scp_to_guest_with_auth(
let _ = channel.wait_close();
Ok(())
})() {
};
match closure() {
Ok(_) => break,
Err(e) => {
counter += 1;
@@ -647,7 +651,7 @@ pub fn ssh_command_ip_with_auth(
let mut counter = 0;
loop {
match (|| -> Result<(), SshCommandError> {
let mut closure = || -> Result<(), SshCommandError> {
let tcp =
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
let mut sess = Session::new().unwrap();
@@ -676,7 +680,9 @@ pub fn ssh_command_ip_with_auth(
} else {
Ok(())
}
})() {
};
match closure() {
Ok(_) => break,
Err(e) => {
counter += 1;
@@ -718,77 +724,18 @@ pub fn ssh_command_ip(
)
}
pub fn exec_host_command_with_retries(command: &str, retries: u32, interval: Duration) -> bool {
for _ in 0..retries {
let s = exec_host_command_output(command).status;
if !s.success() {
eprintln!("\n\n==== retrying in {:?} ===\n\n", interval);
thread::sleep(interval);
} else {
return true;
}
}
false
}
pub fn exec_host_command_status(command: &str) -> ExitStatus {
exec_host_command_output(command).status
std::process::Command::new("bash")
.args(["-c", command])
.status()
.unwrap_or_else(|_| panic!("Expected '{command}' to run"))
}
pub fn exec_host_command_output(command: &str) -> Output {
let output = std::process::Command::new("bash")
std::process::Command::new("bash")
.args(["-c", command])
.output()
.unwrap_or_else(|e| panic!("Expected '{command}' to run. Error: {:?}", e));
if !output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!(
"\n\n==== Start 'exec_host_command' failed ==== \
\n\n---stdout---\n{stdout}\n---stderr---{stderr} \
\n\n==== End 'exec_host_command' failed ====",
);
}
output
}
pub fn check_lines_count(input: &str, line_count: usize) -> bool {
if input.lines().count() == line_count {
true
} else {
eprintln!(
"\n\n==== Start 'check_lines_count' failed ==== \
\n\ninput = {input}\nline_count = {line_count} \
\n\n==== End 'check_lines_count' failed ====",
);
false
}
}
pub fn check_matched_lines_count(input: &str, keywords: Vec<&str>, line_count: usize) -> bool {
let mut matches = String::new();
for line in input.lines() {
if keywords.iter().all(|k| line.contains(k)) {
matches += line;
}
}
if matches.lines().count() == line_count {
true
} else {
eprintln!(
"\n\n==== Start 'check_matched_lines_count' failed ==== \
\nkeywords = {keywords:?}, line_count = {line_count} \
\n\ninput = {input} matches = {matches} \
\n\n==== End 'check_matched_lines_count' failed ====",
);
false
}
.unwrap_or_else(|_| panic!("Expected '{command}' to run"))
}
pub const PIPE_SIZE: i32 = 32 << 20;
@@ -1396,7 +1343,7 @@ pub fn parse_iperf3_output(output: &[u8], sender: bool, bandwidth: bool) -> Resu
})
.map_err(|_| {
eprintln!(
"==== Start iperf3 output ===\n\n{}\n\n=== End iperf3 output ===\n\n",
"=============== iperf3 output ===============\n\n{}\n\n===========end============\n\n",
String::from_utf8_lossy(output)
);
Error::Iperf3Parse
@@ -1474,7 +1421,9 @@ pub fn parse_fio_output(output: &str, fio_ops: &FioOps, num_jobs: u32) -> Result
total_bps
})
.map_err(|_| {
eprintln!("=== Start Fio output ===\n\n{output}\n\n=== End Fio output ===\n\n");
eprintln!(
"=============== Fio output ===============\n\n{output}\n\n===========end============\n\n"
);
Error::FioOutputParse
})
}
@@ -1527,7 +1476,9 @@ pub fn parse_fio_output_iops(output: &str, fio_ops: &FioOps, num_jobs: u32) -> R
total_iops
})
.map_err(|_| {
eprintln!("=== Start Fio output ===\n\n{output}\n\n=== End Fio output ===\n\n");
eprintln!(
"=============== Fio output ===============\n\n{output}\n\n===========end============\n\n"
);
Error::FioOutputParse
})
}
@@ -1660,7 +1611,7 @@ pub fn parse_ethr_latency_output(output: &[u8]) -> Result<Vec<f64>, Error> {
})
.map_err(|_| {
eprintln!(
"=== Start ethr output ===\n\n{}\n\n=== End ethr output ===\n\n",
"=============== ethr output ===============\n\n{}\n\n===========end============\n\n",
String::from_utf8_lossy(output)
);
Error::EthrLogParse

View File

@@ -687,8 +687,6 @@ fn resize_command(
device_id: None,
},
];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, event_path));
}
@@ -860,7 +858,6 @@ fn fw_path(_fw_type: FwType) -> String {
fw_path.to_str().unwrap().to_string()
}
#[derive(Debug)]
struct MetaEvent {
event: String,
device_id: Option<String>,
@@ -913,18 +910,7 @@ fn check_sequential_events(expected_events: &[&MetaEvent], event_file: &str) ->
}
}
let ret = idx == len;
if !ret {
eprintln!(
"\n\n==== Start 'check_sequential_events' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_sequential_events' failed ====",
expected_events, json_events,
);
}
ret
idx == len
}
// Return true if all events from the input 'expected_events' are matched exactly
@@ -936,13 +922,6 @@ fn check_sequential_events_exact(expected_events: &[&MetaEvent], event_file: &st
for (idx, e) in json_events.iter().enumerate() {
if !expected_events[idx].match_with_json_event(e) {
eprintln!(
"\n\n==== Start 'check_sequential_events_exact' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_sequential_events_exact' failed ====",
expected_events, json_events,
);
return false;
}
}
@@ -959,13 +938,6 @@ fn check_latest_events_exact(latest_events: &[&MetaEvent], event_file: &str) ->
for (idx, e) in json_events.iter().enumerate() {
if !latest_events[idx].match_with_json_event(e) {
eprintln!(
"\n\n==== Start 'check_latest_events_exact' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_latest_events_exact' failed ====",
latest_events, json_events,
);
return false;
}
}
@@ -3960,7 +3932,7 @@ mod common_parallel {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let serial_path = guest.tmp_dir.as_path().join("/tmp/serial-output");
let serial_path = guest.tmp_dir.as_path().join("serial-output");
#[cfg(target_arch = "x86_64")]
let console_str: &str = "console=ttyS0";
#[cfg(target_arch = "aarch64")]
@@ -4073,8 +4045,8 @@ mod common_parallel {
fn test_serial_socket_interaction() {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let serial_socket = guest.tmp_dir.as_path().join("/tmp/serial.socket");
let serial_socket_pty = guest.tmp_dir.as_path().join("/tmp/serial.pty");
let serial_socket = guest.tmp_dir.as_path().join("serial.socket");
let serial_socket_pty = guest.tmp_dir.as_path().join("serial.pty");
let serial_option = if cfg!(target_arch = "x86_64") {
" console=ttyS0"
} else {
@@ -4128,12 +4100,7 @@ mod common_parallel {
let r = std::panic::catch_unwind(|| {
// Check that the cloud-hypervisor binary actually terminated
if !output.status.success() {
panic!(
"Cloud Hypervisor process failed to terminate gracefully: {:?}",
output.status
);
}
assert!(output.status.success())
});
handle_child_output(r, &output);
}
@@ -4187,7 +4154,7 @@ mod common_parallel {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let console_path = guest.tmp_dir.as_path().join("/tmp/console-output");
let console_path = guest.tmp_dir.as_path().join("console-output");
let mut child = GuestCommand::new(&guest)
.args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"])
@@ -4248,8 +4215,8 @@ mod common_parallel {
fn test_vfio() {
setup_vfio_network_interfaces();
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new_from_ip_range(Box::new(focal), "172.18", 0);
let jammy = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new_from_ip_range(Box::new(jammy), "172.18", 0);
let mut workload_path = dirs::home_dir().unwrap();
workload_path.push("workloads");
@@ -4354,35 +4321,49 @@ mod common_parallel {
// Let's ssh into it and verify that it's there. If it is it means
// we're in the right guest (The L2 one) because the QEMU L1 guest
// does not have this command line tag.
assert!(check_matched_lines_count(
guest.ssh_command_l2_1("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"],
assert_eq!(
guest
.ssh_command_l2_1("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
));
);
// Let's also verify from the second virtio-net device passed to
// the L2 VM.
assert!(check_matched_lines_count(
guest.ssh_command_l2_2("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"],
assert_eq!(
guest
.ssh_command_l2_2("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
));
);
// Check the amount of PCI devices appearing in L2 VM.
assert!(check_lines_count(
assert_eq!(
guest
.ssh_command_l2_1("ls /sys/bus/pci/devices")
.ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap()
.trim(),
8
));
.trim()
.parse::<u32>()
.unwrap_or_default(),
8,
);
// Check both if /dev/vdc exists and if the block size is 16M in L2 VM
assert!(check_matched_lines_count(
guest.ssh_command_l2_1("lsblk").unwrap().trim(),
vec!["vdc", "16M"],
assert_eq!(
guest
.ssh_command_l2_1("lsblk | grep vdc | grep -c 16M")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
));
);
// Hotplug an extra virtio-net device through L2 VM.
guest
@@ -4400,33 +4381,35 @@ mod common_parallel {
add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123",
)
.unwrap();
assert!(check_matched_lines_count(
vfio_hotplug_output.trim(),
vec!["{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"],
1
));
assert!(vfio_hotplug_output.contains("{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"));
thread::sleep(std::time::Duration::new(10, 0));
// Let's also verify from the third virtio-net device passed to
// the L2 VM. This third device has been hotplugged through the L2
// VM, so this is our way to validate hotplug works for VFIO PCI.
assert!(check_matched_lines_count(
guest.ssh_command_l2_3("cat /proc/cmdline").unwrap().trim(),
vec!["VFIOTAG"],
assert_eq!(
guest
.ssh_command_l2_3("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1
));
);
// Check the amount of PCI devices appearing in L2 VM.
// There should be one more device than before, raising the count
// up to 9 PCI devices.
assert!(check_lines_count(
assert_eq!(
guest
.ssh_command_l2_1("ls /sys/bus/pci/devices")
.ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap()
.trim(),
9
));
.trim()
.parse::<u32>()
.unwrap_or_default(),
9,
);
// Let's now verify that we can correctly remove the virtio-net
// device through the "remove-device" command responsible for
@@ -4442,13 +4425,15 @@ mod common_parallel {
// Check the amount of PCI devices appearing in L2 VM is back down
// to 8 devices.
assert!(check_lines_count(
assert_eq!(
guest
.ssh_command_l2_1("ls /sys/bus/pci/devices")
.ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap()
.trim(),
8
));
.trim()
.parse::<u32>()
.unwrap_or_default(),
8,
);
// Perform memory hotplug in L2 and validate the memory is showing
// up as expected. In order to check, we will use the virtio-net
@@ -5967,8 +5952,6 @@ mod common_parallel {
event: "device-removed".to_string(),
device_id: Some(net_id.to_string()),
}];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path));
// Plug the virtio-net device again
@@ -5992,8 +5975,6 @@ mod common_parallel {
device_id: None,
},
];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path));
// Take a snapshot from the VM
@@ -6016,8 +5997,6 @@ mod common_parallel {
device_id: None,
},
];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path));
});
@@ -6093,12 +6072,6 @@ mod common_parallel {
let r = std::panic::catch_unwind(|| {
// Resume the VM
assert!(remote_command(&api_socket_restored, "resume", None));
// There is no way that we can ensure the 'write()' to the
// event file is completed when the 'resume' request is
// returned successfully, because the 'write()' was done
// asynchronously from a different thread of Cloud
// Hypervisor (e.g. the event-monitor thread).
thread::sleep(std::time::Duration::new(1, 0));
let latest_events = [
&MetaEvent {
event: "resuming".to_string(),
@@ -6278,7 +6251,6 @@ mod common_parallel {
let api_socket = temp_api_path(&guest.tmp_dir);
let kernel_path = direct_kernel_boot_path();
let event_path = temp_event_monitor_path(&guest.tmp_dir);
let mut cmd = GuestCommand::new(&guest);
cmd.args(["--cpus", "boot=1"])
@@ -6289,7 +6261,6 @@ mod common_parallel {
.args(["--net", guest.default_net_string().as_str()])
.args(["--watchdog"])
.args(["--api-socket", &api_socket])
.args(["--event-monitor", format!("path={event_path}").as_str()])
.capture_output();
let mut child = cmd.spawn().unwrap();
@@ -6334,17 +6305,7 @@ mod common_parallel {
{
// Now pause the VM and remain offline for 30s
assert!(remote_command(&api_socket, "pause", None));
let latest_events = [
&MetaEvent {
event: "pausing".to_string(),
device_id: None,
},
&MetaEvent {
event: "paused".to_string(),
device_id: None,
},
];
assert!(check_latest_events_exact(&latest_events, &event_path));
thread::sleep(std::time::Duration::new(30, 0));
assert!(remote_command(&api_socket, "resume", None));
// Check no reboot
@@ -6776,11 +6737,10 @@ mod common_parallel {
.unwrap();
thread::sleep(std::time::Duration::new(2, 0));
assert!(exec_host_command_with_retries(
"/usr/local/bin/spdk-nvme/rpc.py nvmf_create_transport -t VFIOUSER",
3,
std::time::Duration::new(5, 0),
));
assert!(exec_host_command_status(
"/usr/local/bin/spdk-nvme/rpc.py nvmf_create_transport -t VFIOUSER"
)
.success());
assert!(exec_host_command_status(&format!(
"/usr/local/bin/spdk-nvme/rpc.py bdev_aio_create {} test 512",
nvme_dir.join("test-disk.raw").to_str().unwrap()
@@ -6895,7 +6855,9 @@ mod common_parallel {
#[cfg(target_arch = "x86_64")]
fn test_vdpa_block() {
// Before trying to run the test, verify the vdpa_sim_blk module is correctly loaded.
assert!(exec_host_command_status("lsmod | grep vdpa_sim_blk").success());
if !exec_host_command_status("lsmod | grep vdpa_sim_blk").success() {
return;
}
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
@@ -7134,58 +7096,6 @@ mod common_parallel {
handle_child_output(r, &output);
}
#[test]
#[cfg(target_arch = "x86_64")]
fn test_double_tty() {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let mut cmd = GuestCommand::new(&guest);
let api_socket = temp_api_path(&guest.tmp_dir);
let tty_str: &str = "console=hvc0 earlyprintk=ttyS0 ";
// linux printk module enable console log.
let con_dis_str: &str = "console [hvc0] enabled";
// linux printk module disable console log.
let con_enb_str: &str = "bootconsole [earlyser0] disabled";
let kernel_path = direct_kernel_boot_path();
cmd.args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"])
.args(["--kernel", kernel_path.to_str().unwrap()])
.args([
"--cmdline",
DIRECT_KERNEL_BOOT_CMDLINE
.replace("console=hvc0 ", tty_str)
.as_str(),
])
.capture_output()
.default_disks()
.default_net()
.args(["--serial", "tty"])
.args(["--console", "tty"])
.args(["--api-socket", &api_socket]);
let mut child = cmd.spawn().unwrap();
let mut r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(None).unwrap();
});
let _ = child.kill();
let output = child.wait_with_output().unwrap();
if r.is_ok() {
r = std::panic::catch_unwind(|| {
let s = String::from_utf8_lossy(&output.stdout);
assert!(s.contains(tty_str));
assert!(s.contains(con_dis_str));
assert!(s.contains(con_enb_str));
});
}
handle_child_output(r, &output);
}
}
mod dbus_api {
@@ -8022,6 +7932,7 @@ mod windows {
}
#[test]
#[ignore = "See #6037"]
#[cfg(not(feature = "mshv"))]
#[cfg(not(target_arch = "aarch64"))]
fn test_windows_guest_disk_hotplug() {
@@ -8117,6 +8028,7 @@ mod windows {
}
#[test]
#[ignore = "See #6037"]
#[cfg(not(feature = "mshv"))]
#[cfg(not(target_arch = "aarch64"))]
fn test_windows_guest_disk_hotplug_multi() {
@@ -8540,13 +8452,8 @@ mod live_migration {
if !send_success {
let _ = send_migration.kill();
let output = send_migration.wait_with_output().unwrap();
eprintln!(
"\n\n==== Start 'send_migration' output ==== \
\n\n---stdout---\n{}\n\n---stderr---\n{} \
\n\n==== End 'send_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
eprintln!("\n\n==== Start 'send_migration' output ====\n\n---stdout---\n{}\n\n---stderr---\n{}\n\n==== End 'send_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr));
}
// The 'receive-migration' command should be executed successfully within the given timeout
@@ -8562,13 +8469,8 @@ mod live_migration {
if !receive_success {
let _ = receive_migration.kill();
let output = receive_migration.wait_with_output().unwrap();
eprintln!(
"\n\n==== Start 'receive_migration' output ==== \
\n\n---stdout---\n{}\n\n---stderr---\n{} \
\n\n==== End 'receive_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
eprintln!("\n\n==== Start 'receive_migration' output ====\n\n---stdout---\n{}\n\n---stderr---\n{}\n\n==== End 'receive_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr));
}
send_success && receive_success
@@ -9610,6 +9512,7 @@ mod live_migration {
// Require to run ovs-dpdk tests sequentially because they rely on the same ovs-dpdk setup
#[test]
#[ignore = "See #5532"]
#[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))]
fn test_live_migration_ovs_dpdk() {
@@ -9624,6 +9527,7 @@ mod live_migration {
}
#[test]
#[ignore = "See #5532"]
#[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_ovs_dpdk() {
@@ -9721,9 +9625,7 @@ mod rate_limiter {
}
eprintln!(
"\n\n==== Start 'check_rate_limit' failed ==== \
\n\nmeasured={measured}, , lower_limit={lower_limit}, upper_limit={upper_limit} \
\n\n==== End 'check_rate_limit' failed ====\n\n"
"\n\n==== check_rate_limit failed! ====\n\nmeasured={measured}, , lower_limit={lower_limit}, upper_limit={upper_limit}\n\n"
);
false

View File

@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
once_cell = "1.18.0"
serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107"

View File

@@ -6,16 +6,17 @@ edition = "2021"
build = "../build.rs"
[dependencies]
clap = { version = "4.4.7", features = ["wrap_help","cargo"] }
clap = { version = "4.3.11", features = ["wrap_help","cargo"] }
block = { path = "../block" }
env_logger = "0.10.0"
epoll = "4.3.3"
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
option_parser = { path = "../option_parser" }
vhost = { version = "0.9.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.11.0"
vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
vhost-user-backend = "0.10.1"
virtio-bindings = "0.2.0"
virtio-queue = "0.10.0"
vm-memory = "0.13.1"
virtio-queue = "0.9.0"
vm-memory = "0.12.2"
vmm-sys-util = "0.11.0"

View File

@@ -299,10 +299,9 @@ impl VhostUserBlkBackend {
}
}
impl VhostUserBackendMut for VhostUserBlkBackend {
type Bitmap = AtomicBitmap;
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
impl VhostUserBackendMut<VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>, AtomicBitmap>
for VhostUserBlkBackend
{
fn num_queues(&self) -> usize {
self.config.num_queues as usize
}
@@ -351,7 +350,7 @@ impl VhostUserBackendMut for VhostUserBlkBackend {
evset: EventSet,
vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>],
thread_id: usize,
) -> VhostUserBackendResult<()> {
) -> VhostUserBackendResult<bool> {
if evset != EventSet::IN {
return Err(Error::HandleEventNotEpollIn.into());
}
@@ -395,7 +394,7 @@ impl VhostUserBackendMut for VhostUserBlkBackend {
thread.process_queue(&mut vring);
}
Ok(())
Ok(false)
}
_ => Err(Error::HandleEventUnknownEvent.into()),
}

View File

@@ -6,16 +6,16 @@ edition = "2021"
build = "../build.rs"
[dependencies]
clap = { version = "4.4.7", features = ["wrap_help","cargo"] }
clap = { version = "4.3.11", features = ["wrap_help","cargo"] }
env_logger = "0.10.0"
epoll = "4.3.3"
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
net_util = { path = "../net_util" }
option_parser = { path = "../option_parser" }
vhost = { version = "0.9.0", features = ["vhost-user-backend"] }
vhost-user-backend = "0.11.0"
vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
vhost-user-backend = "0.10.1"
virtio-bindings = "0.2.0"
vm-memory = "0.13.1"
vm-memory = "0.12.2"
vmm-sys-util = "0.11.0"

View File

@@ -158,10 +158,9 @@ impl VhostUserNetBackend {
}
}
impl VhostUserBackendMut for VhostUserNetBackend {
type Bitmap = AtomicBitmap;
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
impl VhostUserBackendMut<VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>, AtomicBitmap>
for VhostUserNetBackend
{
fn num_queues(&self) -> usize {
self.num_queues
}
@@ -204,7 +203,7 @@ impl VhostUserBackendMut for VhostUserNetBackend {
_evset: EventSet,
vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>],
thread_id: usize,
) -> VhostUserBackendResult<()> {
) -> VhostUserBackendResult<bool> {
let mut thread = self.threads[thread_id].lock().unwrap();
match device_event {
0 => {
@@ -246,7 +245,7 @@ impl VhostUserBackendMut for VhostUserNetBackend {
_ => return Err(Error::HandleEventUnknownEvent.into()),
}
Ok(())
Ok(false)
}
fn exit_event(&self, thread_index: usize) -> Option<EventFd> {

View File

@@ -15,7 +15,7 @@ byteorder = "1.4.3"
epoll = "4.3.3"
event_monitor = { path = "../event_monitor" }
libc = "0.2.147"
log = "0.4.20"
log = "0.4.17"
net_gen = { path = "../net_gen" }
net_util = { path = "../net_util" }
pci = { path = "../pci" }
@@ -27,12 +27,12 @@ serial_buffer = { path = "../serial_buffer" }
thiserror = "1.0.40"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vhost = { version = "0.9.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] }
vhost = { version = "0.8.1", features = ["vhost-user-master", "vhost-user-slave", "vhost-kern", "vhost-vdpa"] }
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.10.0"
virtio-queue = "0.9.0"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.11.0"

View File

@@ -28,7 +28,7 @@ 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_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
@@ -59,8 +59,6 @@ enum Error {
GuestMemoryRead(vm_memory::guest_memory::Error),
#[error("Failed to write to guest memory: {0}")]
GuestMemoryWrite(vm_memory::guest_memory::Error),
#[error("Failed to write_all output: {0}")]
OutputWriteAll(io::Error),
#[error("Failed to flush output: {0}")]
OutputFlush(io::Error),
#[error("Failed to add used index: {0}")]
@@ -266,18 +264,15 @@ impl ConsoleEpollHandler {
while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
if let Some(out) = &mut self.out {
let mut buf: Vec<u8> = Vec::new();
desc_chain
.memory()
.write_volatile_to(
.write_to(
desc.addr()
.translate_gva(self.access_platform.as_ref(), desc.len() as usize),
&mut buf,
out,
desc.len() as usize,
)
.map_err(Error::GuestMemoryRead)?;
out.write_all(&buf).map_err(Error::OutputWriteAll)?;
out.flush().map_err(Error::OutputFlush)?;
}
trans_queue

View File

@@ -24,7 +24,7 @@ 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_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable};
@@ -75,7 +75,7 @@ impl RngEpollHandler {
// Fill the read with data from the random device on the host.
let len = desc_chain
.memory()
.read_volatile_from(
.read_from(
desc.addr()
.translate_gva(self.access_platform.as_ref(), desc.len() as usize),
&mut self.random_file,

View File

@@ -955,9 +955,8 @@ impl PciDevice for VirtioPciDevice {
fn allocate_bars(
&mut self,
_allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
allocator: &Arc<Mutex<SystemAllocator>>,
mmio_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new();
@@ -996,7 +995,7 @@ impl PciDevice for VirtioPciDevice {
// See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004
let (virtio_pci_bar_addr, region_type) = if use_64bit_bar {
let region_type = PciBarRegionType::Memory64BitRegion;
let addr = mmio64_allocator
let addr = mmio_allocator
.allocate(
settings_bar_addr,
CAPABILITY_BAR_SIZE,
@@ -1006,8 +1005,10 @@ impl PciDevice for VirtioPciDevice {
(addr, region_type)
} else {
let region_type = PciBarRegionType::Memory32BitRegion;
let addr = mmio32_allocator
.allocate(
let addr = allocator
.lock()
.unwrap()
.allocate_mmio_hole_addresses(
settings_bar_addr,
CAPABILITY_BAR_SIZE,
Some(CAPABILITY_BAR_SIZE),
@@ -1077,17 +1078,16 @@ impl PciDevice for VirtioPciDevice {
fn free_bars(
&mut self,
_allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
allocator: &mut SystemAllocator,
mmio_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) {
match bar.region_type() {
PciBarRegionType::Memory32BitRegion => {
mmio32_allocator.free(GuestAddress(bar.addr()), bar.size());
allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size());
}
PciBarRegionType::Memory64BitRegion => {
mmio64_allocator.free(GuestAddress(bar.addr()), bar.size());
mmio_allocator.free(GuestAddress(bar.addr()), bar.size());
}
_ => error!("Unexpected PCI bar type"),
}

View File

@@ -23,7 +23,7 @@ use vhost::vhost_user::message::{
VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
VHOST_USER_CONFIG_OFFSET,
};
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler};
use vhost::vhost_user::{MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
use virtio_bindings::virtio_blk::{
VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_FLUSH,
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_SEG_MAX,
@@ -50,8 +50,8 @@ pub struct State {
impl VersionMapped for State {}
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
struct SlaveReqHandler {}
impl VhostUserMasterReqHandler for SlaveReqHandler {}
pub struct Blk {
common: VirtioCommon,
@@ -294,7 +294,7 @@ impl VirtioDevice for Blk {
self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
// Run a dedicated thread for handling potential reconnections with
// the backend.
@@ -305,7 +305,7 @@ impl VirtioDevice for Blk {
queues,
interrupt_cb,
self.common.acked_features,
backend_req_handler,
slave_req_handler,
kill_evt,
pause_evt,
)?;

View File

@@ -22,11 +22,11 @@ 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,
VhostUserFSSlaveMsg, VhostUserFSSlaveMsgFlags, VhostUserProtocolFeatures,
VhostUserVirtioFeatures, VHOST_USER_FS_SLAVE_ENTRIES,
};
use vhost::vhost_user::{
FrontendReqHandler, HandlerResult, VhostUserFrontend, VhostUserFrontendReqHandler,
HandlerResult, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
};
use virtio_queue::Queue;
use vm_memory::{
@@ -48,19 +48,19 @@ pub struct State {
pub config: VirtioFsConfig,
pub acked_protocol_features: u64,
pub vu_num_queues: usize,
pub backend_req_support: bool,
pub slave_req_support: bool,
}
impl VersionMapped for State {}
struct BackendReqHandler {
struct SlaveReqHandler {
cache_offset: GuestAddress,
cache_size: u64,
mmap_cache_addr: u64,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
}
impl BackendReqHandler {
impl SlaveReqHandler {
// Make sure request is within cache range
fn is_req_valid(&self, offset: u64, len: u64) -> bool {
let end = match offset.checked_add(len) {
@@ -72,16 +72,16 @@ impl BackendReqHandler {
}
}
impl VhostUserFrontendReqHandler for BackendReqHandler {
impl VhostUserMasterReqHandler for SlaveReqHandler {
fn handle_config_change(&self) -> HandlerResult<u64> {
debug!("handle_config_change");
Ok(0)
}
fn fs_backend_map(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_backend_map");
fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_slave_map");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES {
for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let offset = fs.cache_offset[i];
let len = fs.len[i];
@@ -115,10 +115,10 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0)
}
fn fs_backend_unmap(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult<u64> {
debug!("fs_backend_unmap");
fn fs_slave_unmap(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64> {
debug!("fs_slave_unmap");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES {
for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let mut len = fs.len[i];
// Ignore if the length is 0.
@@ -126,7 +126,7 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
continue;
}
// Need to handle a special case where the backend ask for the unmapping
// Need to handle a special case where the slave ask for the unmapping
// of the entire mapping.
let offset = if len == 0xffff_ffff_ffff_ffff {
len = self.cache_size;
@@ -159,10 +159,10 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0)
}
fn fs_backend_sync(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult<u64> {
debug!("fs_backend_sync");
fn fs_slave_sync(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64> {
debug!("fs_slave_sync");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES {
for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let offset = fs.cache_offset[i];
let len = fs.len[i];
@@ -187,11 +187,11 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0)
}
fn fs_backend_io(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_backend_io");
fn fs_slave_io(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_slave_io");
let mut done: u64 = 0;
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES {
for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
// Ignore if the length is 0.
if fs.len[i] == 0 {
continue;
@@ -230,8 +230,8 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
};
while len > 0 {
let ret = if (fs.flags[i] & VhostUserFSBackendMsgFlags::MAP_W)
== VhostUserFSBackendMsgFlags::MAP_W
let ret = if (fs.flags[i] & VhostUserFSSlaveMsgFlags::MAP_W)
== VhostUserFSSlaveMsgFlags::MAP_W
{
debug!("write: foffset={}, len={}", foffset, len);
// SAFETY: FFI call with valid arguments
@@ -298,7 +298,7 @@ pub struct Fs {
// Hold ownership of the memory that is allocated for the device
// which will be automatically dropped when the device is dropped
cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
backend_req_support: bool,
slave_req_support: bool,
seccomp_action: SeccompAction,
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
epoll_thread: Option<thread::JoinHandle<()>>,
@@ -321,7 +321,7 @@ impl Fs {
iommu: bool,
state: Option<State>,
) -> Result<Fs> {
let mut backend_req_support = false;
let mut slave_req_support = false;
// Calculate the actual number of queues needed.
let num_queues = NUM_QUEUE_OFFSET + req_num_queues;
@@ -335,7 +335,7 @@ impl Fs {
acked_protocol_features,
vu_num_queues,
config,
backend_req_support,
slave_req_support,
paused,
) = if let Some(state) = state {
info!("Restoring vhost-user-fs {}", id);
@@ -351,7 +351,7 @@ impl Fs {
state.acked_protocol_features,
state.vu_num_queues,
state.config,
state.backend_req_support,
state.slave_req_support,
true,
)
} else {
@@ -363,10 +363,10 @@ impl Fs {
| VhostUserProtocolFeatures::REPLY_ACK
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
| VhostUserProtocolFeatures::LOG_SHMFD;
let backend_protocol_features =
VhostUserProtocolFeatures::BACKEND_REQ | VhostUserProtocolFeatures::BACKEND_SEND_FD;
let slave_protocol_features =
VhostUserProtocolFeatures::SLAVE_REQ | VhostUserProtocolFeatures::SLAVE_SEND_FD;
if cache.is_some() {
avail_protocol_features |= backend_protocol_features;
avail_protocol_features |= slave_protocol_features;
}
let (acked_features, acked_protocol_features) =
@@ -389,10 +389,10 @@ impl Fs {
return Err(Error::BadQueueNum);
}
if acked_protocol_features & backend_protocol_features.bits()
== backend_protocol_features.bits()
if acked_protocol_features & slave_protocol_features.bits()
== slave_protocol_features.bits()
{
backend_req_support = true;
slave_req_support = true;
}
// Create virtio-fs device configuration.
@@ -411,7 +411,7 @@ impl Fs {
acked_protocol_features,
num_queues,
config,
backend_req_support,
slave_req_support,
false,
)
};
@@ -437,7 +437,7 @@ impl Fs {
id,
config,
cache,
backend_req_support,
slave_req_support,
seccomp_action,
guest_memory: None,
epoll_thread: None,
@@ -453,7 +453,7 @@ impl Fs {
config: self.config,
acked_protocol_features: self.vu_common.acked_protocol_features,
vu_num_queues: self.vu_common.vu_num_queues,
backend_req_support: self.backend_req_support,
slave_req_support: self.slave_req_support,
}
}
}
@@ -507,10 +507,10 @@ impl VirtioDevice for Fs {
self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone());
// Initialize backend communication.
let backend_req_handler = if self.backend_req_support {
// Initialize slave communication.
let slave_req_handler = if self.slave_req_support {
if let Some(cache) = self.cache.as_ref() {
let vu_frontend_req_handler = Arc::new(BackendReqHandler {
let vu_master_req_handler = Arc::new(SlaveReqHandler {
cache_offset: cache.0.addr,
cache_size: cache.0.len,
mmap_cache_addr: cache.0.host_addr,
@@ -518,8 +518,8 @@ impl VirtioDevice for Fs {
});
let mut req_handler =
FrontendReqHandler::new(vu_frontend_req_handler).map_err(|e| {
ActivateError::VhostUserFsSetup(Error::FrontendReqHandlerCreation(e))
MasterReqHandler::new(vu_master_req_handler).map_err(|e| {
ActivateError::VhostUserFsSetup(Error::MasterReqHandlerCreation(e))
})?;
if self.vu_common.acked_protocol_features
@@ -546,7 +546,7 @@ impl VirtioDevice for Fs {
queues,
interrupt_cb,
self.common.acked_features,
backend_req_handler,
slave_req_handler,
kill_evt,
pause_evt,
)?;

View File

@@ -17,7 +17,7 @@ use versionize::Versionize;
use vhost::vhost_user::message::{
VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
};
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontendReqHandler};
use vhost::vhost_user::{MasterReqHandler, VhostUserMasterReqHandler};
use vhost::Error as VhostError;
use virtio_queue::Error as QueueError;
use virtio_queue::Queue;
@@ -61,8 +61,8 @@ pub enum Error {
MemoryRegions(MmapError),
#[error("Failed removing socket path: {0}")]
RemoveSocketPath(io::Error),
#[error("Failed to create frontend: {0}")]
VhostUserCreateFrontend(VhostError),
#[error("Failed to create master: {0}")]
VhostUserCreateMaster(VhostError),
#[error("Failed to open vhost device: {0}")]
VhostUserOpen(VhostError),
#[error("Connection to socket failed")]
@@ -105,10 +105,10 @@ pub enum Error {
VhostIrqRead(io::Error),
#[error("Failed to read vhost eventfd: {0}")]
VhostUserMemoryRegion(MmapError),
#[error("Failed to create the frontend request handler from backend: {0}")]
FrontendReqHandlerCreation(vhost::vhost_user::Error),
#[error("Set backend request fd failed: {0}")]
VhostUserSetBackendRequestFd(vhost::Error),
#[error("Failed to create the master request handler from slave: {0}")]
MasterReqHandlerCreation(vhost::vhost_user::Error),
#[error("Set slave request fd failed: {0}")]
VhostUserSetSlaveRequestFd(vhost::Error),
#[error("Add memory region failed: {0}")]
VhostUserAddMemReg(VhostError),
#[error("Failed getting the configuration: {0}")]
@@ -155,7 +155,7 @@ pub const DEFAULT_VIRTIO_FEATURES: u64 = 1 << VIRTIO_F_RING_INDIRECT_DESC
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
const BACKEND_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
const SLAVE_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
#[derive(Default)]
pub struct Inflight {
@@ -163,7 +163,7 @@ pub struct Inflight {
pub fd: Option<std::fs::File>,
}
pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> {
pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
pub vu: Arc<Mutex<VhostUserHandle>>,
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
pub kill_evt: EventFd,
@@ -174,11 +174,11 @@ pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> {
pub acked_protocol_features: u64,
pub socket_path: String,
pub server: bool,
pub backend_req_handler: Option<FrontendReqHandler<S>>,
pub slave_req_handler: Option<MasterReqHandler<S>>,
pub inflight: Option<Inflight>,
}
impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
pub fn run(
&mut self,
paused: Arc<AtomicBool>,
@@ -191,8 +191,8 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
epoll::Events::EPOLLHUP,
)?;
if let Some(backend_req_handler) = &self.backend_req_handler {
helper.add_event(backend_req_handler.as_raw_fd(), BACKEND_REQ_EVENT)?;
if let Some(slave_req_handler) = &self.slave_req_handler {
helper.add_event(slave_req_handler.as_raw_fd(), SLAVE_REQ_EVENT)?;
}
helper.run(paused, paused_sync, self)?;
@@ -231,7 +231,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
&self.virtio_interrupt,
self.acked_features,
self.acked_protocol_features,
&self.backend_req_handler,
&self.slave_req_handler,
self.inflight.as_mut(),
)
.map_err(|e| {
@@ -255,7 +255,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
}
}
impl<S: VhostUserFrontendReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> {
impl<S: VhostUserMasterReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> {
fn handle_event(
&mut self,
helper: &mut EpollHelper,
@@ -271,9 +271,9 @@ impl<S: VhostUserFrontendReqHandler> EpollHelperHandler for VhostUserEpollHandle
))
})?;
}
BACKEND_REQ_EVENT => {
if let Some(backend_req_handler) = self.backend_req_handler.as_mut() {
backend_req_handler.handle_request().map_err(|e| {
SLAVE_REQ_EVENT => {
if let Some(slave_req_handler) = self.slave_req_handler.as_mut() {
slave_req_handler.handle_request().map_err(|e| {
EpollHelperError::HandleEvent(anyhow!(
"Failed to handle request from vhost-user backend: {:?}",
e
@@ -304,13 +304,13 @@ pub struct VhostUserCommon {
impl VhostUserCommon {
#[allow(clippy::too_many_arguments)]
pub fn activate<T: VhostUserFrontendReqHandler>(
pub fn activate<T: VhostUserMasterReqHandler>(
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
queues: Vec<(usize, Queue, EventFd)>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
acked_features: u64,
backend_req_handler: Option<FrontendReqHandler<T>>,
slave_req_handler: Option<MasterReqHandler<T>>,
kill_evt: EventFd,
pause_evt: EventFd,
) -> std::result::Result<VhostUserEpollHandler<T>, ActivateError> {
@@ -337,7 +337,7 @@ impl VhostUserCommon {
.collect(),
&interrupt_cb,
acked_features,
&backend_req_handler,
&slave_req_handler,
inflight.as_mut(),
)
.map_err(ActivateError::VhostUserSetup)?;
@@ -353,7 +353,7 @@ impl VhostUserCommon {
acked_protocol_features: self.acked_protocol_features,
socket_path: self.socket_path.clone(),
server: self.server,
backend_req_handler,
slave_req_handler,
inflight,
})
}

View File

@@ -20,7 +20,7 @@ use std::vec::Vec;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler};
use vhost::vhost_user::{MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
use virtio_bindings::virtio_net::{
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN,
VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO,
@@ -49,8 +49,8 @@ pub struct State {
impl VersionMapped for State {}
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
struct SlaveReqHandler {}
impl VhostUserMasterReqHandler for SlaveReqHandler {}
pub struct Net {
common: VirtioCommon,
@@ -342,7 +342,7 @@ impl VirtioDevice for Net {
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
}
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
// The backend acknowledged features must not contain VIRTIO_NET_F_MAC
// since we don't expect the backend to handle it.
@@ -357,7 +357,7 @@ impl VirtioDevice for Net {
queues,
interrupt_cb,
backend_acked_features,
backend_req_handler,
slave_req_handler,
kill_evt,
pause_evt,
)?;

View File

@@ -20,9 +20,7 @@ use vhost::vhost_kern::vhost_binding::{VHOST_F_LOG_ALL, VHOST_VRING_F_LOG};
use vhost::vhost_user::message::{
VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
};
use vhost::vhost_user::{
Frontend, FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler,
};
use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
use vhost::{VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData};
use virtio_queue::{Descriptor, Queue, QueueT};
use vm_memory::{
@@ -49,7 +47,7 @@ struct VringInfo {
#[derive(Clone)]
pub struct VhostUserHandle {
vu: Frontend,
vu: Master,
ready: bool,
supports_migration: bool,
shm_log: Option<Arc<MmapRegion>>,
@@ -150,13 +148,13 @@ impl VhostUserHandle {
}
#[allow(clippy::too_many_arguments)]
pub fn setup_vhost_user<S: VhostUserFrontendReqHandler>(
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
&mut self,
mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64,
backend_req_handler: &Option<FrontendReqHandler<S>>,
slave_req_handler: &Option<MasterReqHandler<S>>,
inflight: Option<&mut Inflight>,
) -> Result<()> {
self.vu
@@ -268,10 +266,10 @@ impl VhostUserHandle {
self.enable_vhost_user_vrings(self.queue_indexes.clone(), true)?;
if let Some(backend_req_handler) = backend_req_handler {
if let Some(slave_req_handler) = slave_req_handler {
self.vu
.set_backend_request_fd(&backend_req_handler.get_tx_raw_fd())
.map_err(Error::VhostUserSetBackendRequestFd)?;
.set_slave_request_fd(&slave_req_handler.get_tx_raw_fd())
.map_err(Error::VhostUserSetSlaveRequestFd)?;
}
self.vrings_info = Some(vrings_info);
@@ -335,14 +333,14 @@ impl VhostUserHandle {
}
#[allow(clippy::too_many_arguments)]
pub fn reinitialize_vhost_user<S: VhostUserFrontendReqHandler>(
pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
&mut self,
mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64,
acked_protocol_features: u64,
backend_req_handler: &Option<FrontendReqHandler<S>>,
slave_req_handler: &Option<MasterReqHandler<S>>,
inflight: Option<&mut Inflight>,
) -> Result<()> {
self.set_protocol_features_vhost_user(acked_features, acked_protocol_features)?;
@@ -352,7 +350,7 @@ impl VhostUserHandle {
queues,
virtio_interrupt,
acked_features,
backend_req_handler,
slave_req_handler,
inflight,
)
}
@@ -374,7 +372,7 @@ impl VhostUserHandle {
let (stream, _) = listener.accept().map_err(Error::AcceptConnection)?;
Ok(VhostUserHandle {
vu: Frontend::from_stream(stream, num_queues),
vu: Master::from_stream(stream, num_queues),
ready: false,
supports_migration: false,
shm_log: None,
@@ -387,7 +385,7 @@ impl VhostUserHandle {
// Retry connecting for a full minute
let err = loop {
let err = match Frontend::connect(socket_path, num_queues) {
let err = match Master::connect(socket_path, num_queues) {
Ok(m) => {
return Ok(VhostUserHandle {
vu: m,
@@ -416,7 +414,7 @@ impl VhostUserHandle {
}
}
pub fn socket_handle(&mut self) -> &mut Frontend {
pub fn socket_handle(&mut self) -> &mut Master {
&mut self.vu
}

View File

@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
libc = "0.2.147"
vm-memory = "0.13.1"
vm-memory = "0.12.2"
[target.'cfg(target_arch = "aarch64")'.dependencies]
arch = { path = "../arch" }

View File

@@ -30,6 +30,7 @@ use crate::page_size::get_page_size;
/// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000),
/// #[cfg(target_arch = "x86_64")] 0x10000,
/// GuestAddress(0x10000000), 0x10000000,
/// GuestAddress(0x20000000), 0x100000,
/// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap();
/// #[cfg(target_arch = "x86_64")]
/// assert_eq!(allocator.allocate_irq(), Some(5));
@@ -46,6 +47,7 @@ pub struct SystemAllocator {
#[cfg(target_arch = "x86_64")]
io_address_space: AddressAllocator,
platform_mmio_address_space: AddressAllocator,
mmio_hole_address_space: AddressAllocator,
gsi_allocator: GsiAllocator,
}
@@ -57,6 +59,8 @@ impl SystemAllocator {
/// * `io_size` - (X86) The size of IO memory.
/// * `platform_mmio_base` - The starting address of platform MMIO memory.
/// * `platform_mmio_size` - The size of platform MMIO memory.
/// * `mmio_hole_base` - The starting address of MMIO memory in 32-bit address space.
/// * `mmio_hole_size` - The size of MMIO memory in 32-bit address space.
/// * `apics` - (X86) Vector of APIC's.
///
pub fn new(
@@ -64,6 +68,8 @@ impl SystemAllocator {
#[cfg(target_arch = "x86_64")] io_size: GuestUsize,
platform_mmio_base: GuestAddress,
platform_mmio_size: GuestUsize,
mmio_hole_base: GuestAddress,
mmio_hole_size: GuestUsize,
#[cfg(target_arch = "x86_64")] apics: Vec<GsiApic>,
) -> Option<Self> {
Some(SystemAllocator {
@@ -73,6 +79,7 @@ impl SystemAllocator {
platform_mmio_base,
platform_mmio_size,
)?,
mmio_hole_address_space: AddressAllocator::new(mmio_hole_base, mmio_hole_size)?,
#[cfg(target_arch = "x86_64")]
gsi_allocator: GsiAllocator::new(apics),
#[cfg(target_arch = "aarch64")]
@@ -116,6 +123,20 @@ impl SystemAllocator {
)
}
/// Reserves a section of `size` bytes of MMIO address space.
pub fn allocate_mmio_hole_addresses(
&mut self,
address: Option<GuestAddress>,
size: GuestUsize,
align_size: Option<GuestUsize>,
) -> Option<GuestAddress> {
self.mmio_hole_address_space.allocate(
address,
size,
Some(align_size.unwrap_or_else(get_page_size)),
)
}
#[cfg(target_arch = "x86_64")]
/// Free an IO address range.
/// We can only free a range if it matches exactly an already allocated range.
@@ -128,4 +149,10 @@ impl SystemAllocator {
pub fn free_platform_mmio_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.platform_mmio_address_space.free(address, size)
}
/// Free an MMIO address range from the 32 bits hole.
/// We can only free a range if it matches exactly an already allocated range.
pub fn free_mmio_hole_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.mmio_hole_address_space.free(address, size)
}
}

View File

@@ -15,5 +15,6 @@ hypervisor = { path = "../hypervisor" }
thiserror = "1.0.40"
serde = { version = "1.0.168", features = ["rc", "derive"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.13.1", features = ["backend-mmap"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap"] }
vmm-sys-util = "0.11.0"

View File

@@ -11,4 +11,4 @@ serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic"] }

View File

@@ -12,8 +12,8 @@ use versionize::{VersionMap, Versionize};
pub mod protocol;
/// Global VMM version for versioning
const MAJOR_VERSION: u16 = 37;
const MINOR_VERSION: u16 = 0;
const MAJOR_VERSION: u16 = 36;
const MINOR_VERSION: u16 = 1;
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;
pub trait VersionMapped {

View File

@@ -8,6 +8,6 @@ edition = "2021"
default = []
[dependencies]
log = "0.4.20"
virtio-queue = "0.10.0"
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
log = "0.4.17"
virtio-queue = "0.9.0"
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

View File

@@ -8,7 +8,6 @@ edition = "2021"
default = []
dbus_api = ["blocking", "futures", "zbus"]
guest_debug = ["kvm", "gdbstub", "gdbstub_arch"]
igvm = ["hex", "igvm_parser", "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"]
@@ -25,28 +24,23 @@ bitflags = "2.4.1"
block = { path = "../block" }
blocking = { version = "1.3.0", optional = true }
cfg-if = "1.0.0"
clap = "4.4.7"
clap = "4.3.11"
devices = { path = "../devices" }
epoll = "4.3.3"
event_monitor = { path = "../event_monitor" }
flume = "0.10.14"
futures = { version = "0.3.27", optional = true }
gdbstub = { version = "0.7.0", optional = true }
gdbstub_arch = { version = "0.3.0", optional = true }
hex = { version = "0.4.3", optional = true }
gdbstub = { version = "0.6.4", optional = true }
gdbstub_arch = { version = "0.2.4", 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 }
libc = "0.2.147"
linux-loader = { version = "0.10.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.20"
linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
log = "0.4.17"
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
net_util = { path = "../net_util" }
once_cell = "1.18.0"
option_parser = { path = "../option_parser" }
pci = { path = "../pci" }
range_map_vec = { version = "0.1.0", optional = true }
seccompiler = "0.4.0"
serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107"
@@ -60,12 +54,12 @@ versionize_derive = "0.1.4"
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.10.0"
virtio-queue = "0.9.0"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = { version = "0.13.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
zbus = { version = "3.11.1", optional = true }
zerocopy = { version = "0.7.21", features = ["alloc","derive"] }
zerocopy = { version = "0.7.21", features = ["derive"] }

View File

@@ -106,6 +106,8 @@ pub enum Error {
#[derive(Debug, PartialEq, Eq, Error)]
pub enum ValidationError {
/// Both console and serial are tty.
DoubleTtyMode,
/// No kernel specified
KernelMissing,
/// Missing file value for console
@@ -187,6 +189,7 @@ impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ValidationError::*;
match self {
DoubleTtyMode => write!(f, "Console mode tty specified for both serial and console"),
KernelMissing => write!(f, "No kernel specified"),
ConsoleFileMissing => write!(f, "Path missing when using file console mode"),
ConsoleSocketPathMissing => write!(f, "Path missing when using socket console mode"),
@@ -398,8 +401,6 @@ pub struct VmParams<'a> {
pub gdb: bool,
pub platform: Option<&'a str>,
pub tpm: Option<&'a str>,
#[cfg(feature = "igvm")]
pub igvm: Option<&'a str>,
}
impl<'a> VmParams<'a> {
@@ -453,8 +454,6 @@ impl<'a> VmParams<'a> {
#[cfg(feature = "guest_debug")]
let gdb = args.contains_id("gdb");
let tpm: Option<&str> = args.get_one::<String>("tpm").map(|x| x as &str);
#[cfg(feature = "igvm")]
let igvm = args.get_one::<String>("igvm").map(|x| x as &str);
VmParams {
cpus,
memory,
@@ -484,8 +483,6 @@ impl<'a> VmParams<'a> {
gdb,
platform,
tpm,
#[cfg(feature = "igvm")]
igvm,
}
}
}
@@ -1933,18 +1930,9 @@ impl VmConfig {
}
}
// The 'conflict' check is introduced in commit 24438e0390d3
// (vm-virtio: Enable the vmm support for virtio-console).
//
// Allow simultaneously set serial and console as TTY mode, for
// someone want to use virtio console for better performance, and
// want to keep legacy serial to catch boot stage logs for debug.
// Using such double tty mode, you need to configure the kernel
// properly, such as:
// "console=hvc0 earlyprintk=ttyS0"
if self.console.mode == ConsoleOutputMode::Tty && self.serial.mode == ConsoleOutputMode::Tty
{
warn!("Using TTY output for both virtio-console and serial port");
return Err(ValidationError::DoubleTtyMode);
}
if self.console.mode == ConsoleOutputMode::File && self.console.file.is_none() {
@@ -2289,21 +2277,12 @@ impl VmConfig {
numa = Some(numa_config_list);
}
#[cfg(not(feature = "igvm"))]
let payload_present = vm_params.kernel.is_some() || vm_params.firmware.is_some();
#[cfg(feature = "igvm")]
let payload_present =
vm_params.kernel.is_some() || vm_params.firmware.is_some() || vm_params.igvm.is_some();
let payload = if payload_present {
let payload = if vm_params.kernel.is_some() || vm_params.firmware.is_some() {
Some(PayloadConfig {
kernel: vm_params.kernel.map(PathBuf::from),
initramfs: vm_params.initramfs.map(PathBuf::from),
cmdline: vm_params.cmdline.map(|s| s.to_string()),
firmware: vm_params.firmware.map(PathBuf::from),
#[cfg(feature = "igvm")]
igvm: vm_params.igvm.map(PathBuf::from),
})
} else {
None
@@ -3131,7 +3110,10 @@ mod tests {
let mut invalid_config = valid_config.clone();
invalid_config.serial.mode = ConsoleOutputMode::Tty;
invalid_config.console.mode = ConsoleOutputMode::Tty;
assert!(valid_config.validate().is_ok());
assert_eq!(
invalid_config.validate(),
Err(ValidationError::DoubleTtyMode)
);
let mut invalid_config = valid_config.clone();
invalid_config.payload = None;

View File

@@ -1784,24 +1784,6 @@ impl CpuManager {
pub(crate) fn vcpus_kill_signalled(&self) -> &Arc<AtomicBool> {
&self.vcpus_kill_signalled
}
#[cfg(feature = "igvm")]
pub(crate) fn get_cpuid_leaf(
&self,
cpu_id: u8,
eax: u32,
ecx: u32,
xfem: u64,
xss: u64,
) -> Result<[u32; 4]> {
let leaf_info = self.vcpus[usize::from(cpu_id)]
.lock()
.unwrap()
.vcpu
.get_cpuid_values(eax, ecx, xfem, xss)
.unwrap();
Ok(leaf_info)
}
}
struct Cpu {

View File

@@ -561,8 +561,7 @@ pub(crate) struct AddressManager {
pub(crate) mmio_bus: Arc<Bus>,
pub(crate) vm: Arc<dyn hypervisor::Vm>,
device_tree: Arc<Mutex<DeviceTree>>,
pci_mmio32_allocators: Vec<Arc<Mutex<AddressAllocator>>>,
pci_mmio64_allocators: Vec<Arc<Mutex<AddressAllocator>>>,
pci_mmio_allocators: Vec<Arc<Mutex<AddressAllocator>>>,
}
impl DeviceRelocation for AddressManager {
@@ -605,35 +604,56 @@ impl DeviceRelocation for AddressManager {
error!("I/O region is not supported");
}
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
let allocators = if region_type == PciBarRegionType::Memory32BitRegion {
&self.pci_mmio32_allocators
// Update system allocator
if region_type == PciBarRegionType::Memory32BitRegion {
self.allocator
.lock()
.unwrap()
.free_mmio_hole_addresses(GuestAddress(old_base), len as GuestUsize);
self.allocator
.lock()
.unwrap()
.allocate_mmio_hole_addresses(
Some(GuestAddress(new_base)),
len as GuestUsize,
Some(len),
)
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"failed allocating new 32 bits MMIO range",
)
})?;
} else {
&self.pci_mmio64_allocators
};
// Find the specific allocator that this BAR was allocated from and use it for new one
for allocator in &self.pci_mmio_allocators {
let allocator_base = allocator.lock().unwrap().base();
let allocator_end = allocator.lock().unwrap().end();
// Find the specific allocator that this BAR was allocated from and use it for new one
for allocator in allocators {
let allocator_base = allocator.lock().unwrap().base();
let allocator_end = allocator.lock().unwrap().end();
if old_base >= allocator_base.0 && old_base <= allocator_end.0 {
allocator
.lock()
.unwrap()
.free(GuestAddress(old_base), len as GuestUsize);
if old_base >= allocator_base.0 && old_base <= allocator_end.0 {
allocator
.lock()
.unwrap()
.free(GuestAddress(old_base), len as GuestUsize);
allocator
.lock()
.unwrap()
.allocate(Some(GuestAddress(new_base)), len as GuestUsize, Some(len))
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"failed allocating new MMIO range",
allocator
.lock()
.unwrap()
.allocate(
Some(GuestAddress(new_base)),
len as GuestUsize,
Some(len),
)
})?;
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"failed allocating new 64 bits MMIO range",
)
})?;
break;
break;
}
}
}
@@ -987,40 +1007,22 @@ 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 start_of_device_area = memory_manager.lock().unwrap().start_of_device_area().0;
let end_of_device_area = memory_manager.lock().unwrap().end_of_device_area().0;
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)
}
// Start each PCI segment range on a 4GiB boundary
let pci_segment_size = (end_of_device_area - start_of_device_area + 1)
/ ((4 << 30) * num_pci_segments as u64)
* (4 << 30);
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;
let pci_mmio32_allocators = create_mmio_allocators(
start_of_mmio32_area,
end_of_mmio32_area,
num_pci_segments,
4 << 10,
);
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,
4 << 30,
);
let mut pci_mmio_allocators = vec![];
for i in 0..num_pci_segments as u64 {
let mmio_start = start_of_device_area + i * pci_segment_size;
let allocator = Arc::new(Mutex::new(
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_size).unwrap(),
));
pci_mmio_allocators.push(allocator)
}
let address_manager = Arc::new(AddressManager {
allocator: memory_manager.lock().unwrap().allocator(),
@@ -1029,8 +1031,7 @@ impl DeviceManager {
mmio_bus,
vm: vm.clone(),
device_tree: Arc::clone(&device_tree),
pci_mmio32_allocators,
pci_mmio64_allocators,
pci_mmio_allocators,
});
// First we create the MSI interrupt manager, the legacy one is created
@@ -1060,8 +1061,7 @@ impl DeviceManager {
let mut pci_segments = vec![PciSegment::new_default_segment(
&address_manager,
Arc::clone(&address_manager.pci_mmio32_allocators[0]),
Arc::clone(&address_manager.pci_mmio64_allocators[0]),
Arc::clone(&address_manager.pci_mmio_allocators[0]),
&pci_irq_slots,
)?];
@@ -1070,8 +1070,7 @@ impl DeviceManager {
i as u16,
numa_node_id_from_pci_segment_id(&numa_nodes, i as u16),
&address_manager,
Arc::clone(&address_manager.pci_mmio32_allocators[i]),
Arc::clone(&address_manager.pci_mmio64_allocators[i]),
Arc::clone(&address_manager.pci_mmio_allocators[i]),
&pci_irq_slots,
)?);
}
@@ -2464,8 +2463,8 @@ impl DeviceManager {
virtio_devices::Net::new(
id.clone(),
Some(tap_if_name),
Some(net_cfg.ip),
Some(net_cfg.mask),
None,
None,
Some(net_cfg.mac),
&mut net_cfg.host_mac,
net_cfg.mtu,
@@ -2766,7 +2765,7 @@ impl DeviceManager {
// The memory needs to be 2MiB aligned in order to support
// hugepages.
self.pci_segments[pmem_cfg.pci_segment as usize]
.mem64_allocator
.allocator
.lock()
.unwrap()
.allocate(
@@ -2781,7 +2780,7 @@ impl DeviceManager {
// The memory needs to be 2MiB aligned in order to support
// hugepages.
let base = self.pci_segments[pmem_cfg.pci_segment as usize]
.mem64_allocator
.allocator
.lock()
.unwrap()
.allocate(None, size as GuestUsize, Some(0x0020_0000))
@@ -3368,11 +3367,7 @@ impl DeviceManager {
.allocate_bars(
&self.address_manager.allocator,
&mut self.pci_segments[segment_id as usize]
.mem32_allocator
.lock()
.unwrap(),
&mut self.pci_segments[segment_id as usize]
.mem64_allocator
.allocator
.lock()
.unwrap(),
resources,
@@ -4085,11 +4080,7 @@ impl DeviceManager {
.free_bars(
&mut self.address_manager.allocator.lock().unwrap(),
&mut self.pci_segments[pci_segment_id as usize]
.mem32_allocator
.lock()
.unwrap(),
&mut self.pci_segments[pci_segment_id as usize]
.mem64_allocator
.allocator
.lock()
.unwrap(),
)

View File

@@ -243,7 +243,7 @@ impl MultiThreadBase for GdbStub {
start_addr: <Self::Arch as Arch>::Usize,
data: &mut [u8],
tid: Tid,
) -> TargetResult<usize, Self> {
) -> TargetResult<(), Self> {
match self.vm_request(
GdbRequestPayload::ReadMem(GuestAddress(start_addr), data.len()),
tid_to_cpuid(tid),
@@ -252,7 +252,7 @@ impl MultiThreadBase for GdbStub {
for (dst, v) in data.iter_mut().zip(r.iter()) {
*dst = *v;
}
Ok(std::cmp::min(data.len(), r.len()))
Ok(())
}
Ok(s) => {
error!("Unexpected response for ReadMem: {:?}", s);

View File

@@ -1,374 +0,0 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2023, Microsoft Corporation
//
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::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 std::collections::HashMap;
use std::ffi::CString;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::mem::size_of;
use std::sync::{Arc, Mutex};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("command line is not a valid C string")]
InvalidCommandLine(#[source] std::ffi::NulError),
#[error("failed to read igvm file")]
Igvm(#[source] std::io::Error),
#[error("invalid igvm file")]
InvalidIgvmFile(#[source] igvm_parser::Error),
#[error("loader error")]
Loader(#[source] crate::igvm::loader::Error),
#[error("parameter too large for parameter area")]
ParameterTooLarge,
#[error("Error importing isolated pages: {0}")]
ImportIsolatedPages(#[source] hypervisor::HypervisorVmError),
#[error("Error completing importing isolated pages: {0}")]
CompleteIsolatedImport(#[source] hypervisor::HypervisorVmError),
}
#[allow(dead_code)]
#[derive(Copy, Clone)]
struct GpaPages {
pub gpa: u64,
pub page_type: u32,
pub page_size: u32,
}
#[derive(Debug)]
enum ParameterAreaState {
/// Parameter area has been declared via a ParameterArea header.
Allocated { data: Vec<u8>, max_size: u64 },
/// Parameter area inserted and invalid to use.
Inserted,
}
// Import a parameter to the given parameter area.
fn import_parameter(
parameter_areas: &mut HashMap<u32, ParameterAreaState>,
info: &IGVM_VHS_PARAMETER,
parameter: &[u8],
) -> Result<(), Error> {
let (parameter_area, max_size) = match parameter_areas
.get_mut(&info.parameter_area_index)
.expect("parameter area should be present")
{
ParameterAreaState::Allocated { data, max_size } => (data, max_size),
ParameterAreaState::Inserted => panic!("igvmfile is not valid"),
};
let offset = info.byte_offset as usize;
let end_of_parameter = offset + parameter.len();
if end_of_parameter > *max_size as usize {
// TODO: tracing for which parameter was too big?
return Err(Error::ParameterTooLarge);
}
if parameter_area.len() < end_of_parameter {
parameter_area.resize(end_of_parameter, 0);
}
parameter_area[offset..end_of_parameter].copy_from_slice(parameter);
Ok(())
}
///
/// Load the given IGVM file to guest memory.
/// Right now it only supports SNP based isolation.
/// We can boot legacy VM with an igvm file without
/// any isolation.
///
pub fn load_igvm(
mut file: &std::fs::File,
memory_manager: Arc<Mutex<MemoryManager>>,
cpu_manager: Arc<Mutex<CpuManager>>,
cmdline: &str,
) -> Result<Box<IgvmLoadedInfo>, Error> {
let mut loaded_info: Box<IgvmLoadedInfo> = Box::default();
let command_line = CString::new(cmdline).map_err(Error::InvalidCommandLine)?;
let mut file_contents = Vec::new();
let memory = memory_manager.lock().as_ref().unwrap().guest_memory();
let mut gpas: Vec<GpaPages> = Vec::new();
let proc_count = cpu_manager.lock().unwrap().vcpus().len() as u32;
file.seek(SeekFrom::Start(0)).map_err(Error::Igvm)?;
file.read_to_end(&mut file_contents).map_err(Error::Igvm)?;
let igvm_file = IgvmFile::new_from_binary(&file_contents, Some(IsolationType::Snp))
.map_err(Error::InvalidIgvmFile)?;
let mask = match &igvm_file.platforms()[0] {
IgvmPlatformHeader::SupportedPlatform(info) => {
debug_assert!(info.platform_type == IgvmPlatformType::SEV_SNP);
info.compatibility_mask
}
};
let mut loader = Loader::new(memory);
let mut parameter_areas: HashMap<u32, ParameterAreaState> = HashMap::new();
for header in igvm_file.directives() {
debug_assert!(header.compatibility_mask().unwrap_or(mask) & mask == mask);
match header {
IgvmDirectiveHeader::PageData {
gpa,
compatibility_mask: _,
flags,
data_type,
data,
} => {
debug_assert!(data.len() as u64 % HV_PAGE_SIZE == 0);
// TODO: only 4k or empty page data supported right now
assert!(data.len() as u64 == HV_PAGE_SIZE || data.is_empty());
let acceptance = match *data_type {
IgvmPageDataType::NORMAL => {
if flags.unmeasured() {
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_UNMEASURED,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
BootPageAcceptance::ExclusiveUnmeasured
} else {
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_NORMAL,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
BootPageAcceptance::Exclusive
}
}
IgvmPageDataType::SECRETS => {
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_SECRETS,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
BootPageAcceptance::SecretsPage
}
IgvmPageDataType::CPUID_DATA => {
// SAFETY: CPUID is readonly
unsafe {
let cpuid_page_p: *mut hv_psp_cpuid_page =
data.as_ptr() as *mut hv_psp_cpuid_page; // as *mut hv_psp_cpuid_page;
let cpuid_page: &mut hv_psp_cpuid_page = &mut *cpuid_page_p;
for i in 0..cpuid_page.count {
let leaf = cpuid_page.cpuid_leaf_info[i as usize];
let mut in_leaf = cpu_manager
.lock()
.unwrap()
.get_cpuid_leaf(
0,
leaf.eax_in,
leaf.ecx_in,
leaf.xfem_in,
leaf.xss_in,
)
.unwrap();
if leaf.eax_in == 1 {
in_leaf[2] &= 0x7FFFFFFF;
}
cpuid_page.cpuid_leaf_info[i as usize].eax_out = in_leaf[0];
cpuid_page.cpuid_leaf_info[i as usize].ebx_out = in_leaf[1];
cpuid_page.cpuid_leaf_info[i as usize].ecx_out = in_leaf[2];
cpuid_page.cpuid_leaf_info[i as usize].edx_out = in_leaf[3];
}
}
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_CPUID,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
BootPageAcceptance::CpuidPage
}
// TODO: other data types SNP / TDX only, unsupported
_ => todo!("unsupported IgvmPageDataType"),
};
loader
.import_pages(gpa / HV_PAGE_SIZE, 1, acceptance, data)
.map_err(Error::Loader)?;
}
IgvmDirectiveHeader::ParameterArea {
number_of_bytes,
parameter_area_index,
initial_data,
} => {
debug_assert!(number_of_bytes % HV_PAGE_SIZE == 0);
debug_assert!(
initial_data.is_empty() || initial_data.len() as u64 == *number_of_bytes
);
// Allocate a new parameter area. It must not be already used.
if parameter_areas
.insert(
*parameter_area_index,
ParameterAreaState::Allocated {
data: initial_data.clone(),
max_size: *number_of_bytes,
},
)
.is_some()
{
panic!("IgvmFile is not valid, invalid invariant");
}
}
IgvmDirectiveHeader::VpCount(info) => {
import_parameter(&mut parameter_areas, info, proc_count.as_bytes())?;
}
IgvmDirectiveHeader::MmioRanges(_info) => {
todo!("unsupported IgvmPageDataType");
}
IgvmDirectiveHeader::MemoryMap(_info) => {
todo!("Not implemented");
}
IgvmDirectiveHeader::CommandLine(info) => {
import_parameter(&mut parameter_areas, info, command_line.as_bytes_with_nul())?;
}
IgvmDirectiveHeader::RequiredMemory {
gpa,
compatibility_mask: _,
number_of_bytes,
vtl2_protectable: _,
} => {
let memory_type = StartupMemoryType::Ram;
loaded_info.gpas.push(*gpa);
loader
.verify_startup_memory_available(
gpa / HV_PAGE_SIZE,
*number_of_bytes as u64 / HV_PAGE_SIZE,
memory_type,
)
.map_err(Error::Loader)?;
}
IgvmDirectiveHeader::SnpVpContext {
gpa,
compatibility_mask: _,
vp_index,
vmsa,
} => {
assert_eq!(gpa % HV_PAGE_SIZE, 0);
let mut data: [u8; 4096] = [0; 4096];
let len = size_of::<SevVmsa>();
loaded_info.vmsa_gpa = *gpa;
loaded_info.vmsa = **vmsa;
// Only supported for index zero
if *vp_index == 0 {
data[..len].copy_from_slice(vmsa.as_bytes());
loader
.import_pages(gpa / HV_PAGE_SIZE, 1, BootPageAcceptance::VpContext, &data)
.map_err(Error::Loader)?;
}
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_VMSA,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
}
IgvmDirectiveHeader::SnpIdBlock {
compatibility_mask,
author_key_enabled,
reserved,
ld,
family_id,
image_id,
version,
guest_svn,
id_key_algorithm,
author_key_algorithm,
id_key_signature,
id_public_key,
author_key_signature,
author_public_key,
} => {
loaded_info.snp_id_block.compatibility_mask = *compatibility_mask;
loaded_info.snp_id_block.author_key_enabled = *author_key_enabled;
loaded_info.snp_id_block.reserved = *reserved;
loaded_info.snp_id_block.ld = *ld;
loaded_info.snp_id_block.family_id = *family_id;
loaded_info.snp_id_block.image_id = *image_id;
loaded_info.snp_id_block.version = *version;
loaded_info.snp_id_block.guest_svn = *guest_svn;
loaded_info.snp_id_block.id_key_algorithm = *id_key_algorithm;
loaded_info.snp_id_block.author_key_algorithm = *author_key_algorithm;
loaded_info.snp_id_block.id_key_signature = **id_key_signature;
loaded_info.snp_id_block.id_public_key = **id_public_key;
loaded_info.snp_id_block.author_key_signature = **author_key_signature;
loaded_info.snp_id_block.author_public_key = **author_public_key;
}
IgvmDirectiveHeader::X64VbsVpContext {
vtl: _,
registers: _,
compatibility_mask: _,
} => {
todo!("VbsVpContext not supported");
}
IgvmDirectiveHeader::VbsMeasurement { .. } => {
todo!("VbsMeasurement not supported")
}
IgvmDirectiveHeader::ParameterInsert(IGVM_VHS_PARAMETER_INSERT {
gpa,
compatibility_mask: _,
parameter_area_index,
}) => {
debug_assert!(gpa % HV_PAGE_SIZE == 0);
let area = parameter_areas
.get_mut(parameter_area_index)
.expect("igvmfile should be valid");
match area {
ParameterAreaState::Allocated { data, max_size } => loader
.import_pages(
gpa / HV_PAGE_SIZE,
*max_size / HV_PAGE_SIZE,
BootPageAcceptance::ExclusiveUnmeasured,
data,
)
.map_err(Error::Loader)?,
ParameterAreaState::Inserted => panic!("igvmfile is invalid, multiple insert"),
}
*area = ParameterAreaState::Inserted;
gpas.push(GpaPages {
gpa: *gpa,
page_type: hv_isolated_page_type_HV_ISOLATED_PAGE_TYPE_UNMEASURED,
page_size: hv_isolated_page_size_HV_ISOLATED_PAGE_SIZE_4KB,
});
}
IgvmDirectiveHeader::ErrorRange { .. } => {
todo!("Error Range not supported")
}
_ => {
todo!("Header not supported!!")
}
}
}
debug!("Dumping the contents of VMSA page: {:x?}", loaded_info.vmsa);
Ok(loaded_info)
}

View File

@@ -1,143 +0,0 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2023, Microsoft Corporation
//
use crate::igvm::{BootPageAcceptance, StartupMemoryType, HV_PAGE_SIZE};
use range_map_vec::{Entry, RangeMap};
use thiserror::Error;
use vm_memory::bitmap::AtomicBitmap;
use vm_memory::{
Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
GuestMemoryRegion,
};
/// Structure to hold the guest memory info/layout to check
/// the if the memory is accepted within the layout.
/// Adds up the total bytes written to the guest memory
pub struct Loader {
memory: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>,
accepted_ranges: RangeMap<u64, BootPageAcceptance>,
bytes_written: u64,
}
#[derive(Debug)]
pub struct ImportRegion {
pub page_base: u64,
pub page_count: u64,
pub acceptance: BootPageAcceptance,
}
#[derive(Debug, Error)]
pub enum Error {
#[error("overlaps with existing import region {0:?}")]
OverlapsExistingRegion(ImportRegion),
#[error("memory unavailable")]
MemoryUnavailable,
#[error("failed to import pages")]
ImportPagesFailed,
#[error("invalid vp context memory")]
InvalidVpContextMemory(&'static str),
#[error("data larger than imported region")]
DataTooLarge,
}
impl Loader {
pub fn new(memory: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>) -> Loader {
Loader {
memory,
accepted_ranges: RangeMap::new(),
bytes_written: 0,
}
}
/// Accept a new page range with a given acceptance into the map of accepted ranges.
pub fn accept_new_range(
&mut self,
page_base: u64,
page_count: u64,
acceptance: BootPageAcceptance,
) -> Result<(), Error> {
let page_end = page_base + page_count - 1;
match self.accepted_ranges.entry(page_base..=page_end) {
Entry::Overlapping(entry) => {
let &(overlap_start, overlap_end, overlap_acceptance) = entry.get();
Err(Error::OverlapsExistingRegion(ImportRegion {
page_base: overlap_start,
page_count: overlap_end - overlap_start + 1,
acceptance: overlap_acceptance,
}))
}
Entry::Vacant(entry) => {
entry.insert(acceptance);
Ok(())
}
}
}
pub fn import_pages(
&mut self,
page_base: u64,
page_count: u64,
acceptance: BootPageAcceptance,
data: &[u8],
) -> Result<(), Error> {
// Page count must be larger or equal to data.
if page_count * HV_PAGE_SIZE < data.len() as u64 {
return Err(Error::DataTooLarge);
}
// Track accepted ranges for duplicate imports.
self.accept_new_range(page_base, page_count, acceptance)?;
let bytes_written = self
.memory
.memory()
.write(data, GuestAddress(page_base * HV_PAGE_SIZE))
.map_err(|_e| {
debug!("Importing pages failed due to MemoryError");
Error::MemoryUnavailable
})?;
if bytes_written != (page_count * HV_PAGE_SIZE) as usize {
return Err(Error::ImportPagesFailed);
}
self.bytes_written += bytes_written as u64;
Ok(())
}
pub fn verify_startup_memory_available(
&mut self,
page_base: u64,
page_count: u64,
memory_type: StartupMemoryType,
) -> Result<(), Error> {
if memory_type != StartupMemoryType::Ram {
return Err(Error::MemoryUnavailable);
}
let mut memory_found = false;
for range in self.memory.memory().iter() {
// Today, the memory layout only describes normal ram and mmio. Thus the memory
// request must live completely within a single range, since any gaps are mmio.
let base_address = page_base * HV_PAGE_SIZE;
let end_address = base_address + (page_count * HV_PAGE_SIZE) - 1;
if base_address >= range.start_addr().0 && base_address < range.last_addr().0 {
if end_address > range.last_addr().0 {
debug!("startup memory end bigger than the current range");
return Err(Error::MemoryUnavailable);
}
memory_found = true;
}
}
if memory_found {
Ok(())
} else {
debug!("no valid memory range available for startup memory verify");
Err(Error::MemoryUnavailable)
}
}
}

View File

@@ -1,81 +0,0 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
// Copyright © 2023, Microsoft Corporation
//
/*
* The IGVM(Independent Guest Virtual Machine) file format
* is designed to encapsulate all information required to
* launch a virtual machine on any given virtualization stack,
* with support for different isolation technologies such as
* AMD SEV-SNP and Intel TDX.
* At a conceptual level, this file format is a set of commands created
* by the tool that generated the file, used by the loader to construct
* the initial guest state. The file format also contains measurement
* information that the underlying platform will use to confirm that
* the file was loaded correctly and signed by the appropriate authorities.
*
* The IGVM file is generated by the tool:
* https://github.com/microsoft/igvm-tooling
*
* The IGVM file is parsed by the following crates:
* https://github.com/microsoft/igvm
*
* This module takes the IGVM file, parses it, and loads it to the
* guest memory. Currently igvm only supported on Microsoft Hypervisor, as
* booting a legacy VM, as well as SNP based isolated VM.
*/
pub mod igvm_loader;
mod loader;
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
use igvm_parser::snp_defs::SevVmsa;
use zerocopy::FromZeroes;
#[derive(Debug, Clone)]
pub struct IgvmLoadedInfo {
pub gpas: Vec<u64>,
pub vmsa_gpa: u64,
pub snp_id_block: IGVM_VHS_SNP_ID_BLOCK,
pub vmsa: SevVmsa,
}
impl Default for IgvmLoadedInfo {
fn default() -> Self {
IgvmLoadedInfo {
gpas: Vec::new(),
vmsa_gpa: 0,
snp_id_block: IGVM_VHS_SNP_ID_BLOCK::new_zeroed(),
vmsa: SevVmsa::new_zeroed(),
}
}
}
pub const HV_PAGE_SIZE: u64 = 4096;
/// The page acceptance used for importing pages into the initial launch context of the guest.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BootPageAcceptance {
/// The page is accepted exclusive (no host visibility) and the page data is measured.
Exclusive,
/// The page is accepted exclusive (no host visibility) and the page data is unmeasured.
ExclusiveUnmeasured,
/// The page contains hardware-specific VP context information.
VpContext,
/// This page communicates error information to the host.
ErrorPage,
/// This page communicates hardware-specific secret information and the page data is unmeasured.
SecretsPage,
/// This page includes guest-specified CPUID information.
CpuidPage,
/// This page should include the enumeration of extended state CPUID leaves.
CpuidExtendedStatePage,
}
/// The startup memory type used to notify a well behaved host that memory should be present before attempting to
/// start the guest.
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq)]
pub enum StartupMemoryType {
/// The range is normal memory.
Ram,
}

View File

@@ -51,7 +51,6 @@ use std::{result, thread};
use thiserror::Error;
use tracer::trace_scoped;
use vm_memory::bitmap::AtomicBitmap;
use vm_memory::{ReadVolatile, WriteVolatile};
use vm_migration::{protocol::*, Migratable};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vmm_sys_util::eventfd::EventFd;
@@ -69,8 +68,6 @@ pub mod device_manager;
pub mod device_tree;
#[cfg(feature = "guest_debug")]
mod gdb;
#[cfg(feature = "igvm")]
mod igvm;
pub mod interrupt;
pub mod memory_manager;
pub mod migration;
@@ -304,8 +301,6 @@ pub fn feature_list() -> Vec<String> {
"dhat-heap".to_string(),
#[cfg(feature = "guest_debug")]
"guest_debug".to_string(),
#[cfg(feature = "igvm")]
"igvm".to_string(),
#[cfg(feature = "io_uring")]
"io_uring".to_string(),
#[cfg(feature = "kvm")]
@@ -1454,7 +1449,7 @@ impl Vmm {
memory_manager: &mut MemoryManager,
) -> std::result::Result<(), MigratableError>
where
T: Read + ReadVolatile + Write,
T: Read + Write,
{
// Read table
let table = MemoryRangeTable::read_from(socket, req.length())?;
@@ -1613,7 +1608,7 @@ impl Vmm {
socket: &mut T,
) -> result::Result<bool, MigratableError>
where
T: Read + Write + WriteVolatile,
T: Read + Write,
{
// Send (dirty) memory table
let table = vm.dirty_log()?;
@@ -1690,7 +1685,7 @@ impl Vmm {
},
)
.map_err(|e| {
MigratableError::MigrateSend(anyhow!("Error generating common cpuid': {:?}", e))
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid': {:?}", e))
})?
};

View File

@@ -16,7 +16,7 @@ use acpi_tables::{aml, Aml};
use anyhow::anyhow;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
use arch::RegionType;
use arch::{layout, RegionType};
#[cfg(target_arch = "x86_64")]
use devices::ioapic;
#[cfg(target_arch = "aarch64")]
@@ -30,10 +30,8 @@ use std::collections::HashMap;
use std::convert::TryInto;
use std::ffi;
use std::fs::{File, OpenOptions};
use std::io::{self};
use std::io::{self, Read};
use std::ops::{BitAnd, Deref, Not, Sub};
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use std::os::fd::AsFd;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::path::PathBuf;
use std::result;
@@ -49,9 +47,8 @@ use vm_device::BusDevice;
use vm_memory::bitmap::AtomicBitmap;
use vm_memory::guest_memory::FileOffset;
use vm_memory::{
mmap::MmapRegionError, Address, Error as MmapError, GuestAddress, GuestAddressSpace,
mmap::MmapRegionError, Address, Bytes, Error as MmapError, GuestAddress, GuestAddressSpace,
GuestMemory, GuestMemoryAtomic, GuestMemoryError, GuestMemoryRegion, GuestUsize, MmapRegion,
ReadVolatile,
};
use vm_migration::{
protocol::MemoryRange, protocol::MemoryRangeTable, Migratable, MigratableError, Pausable,
@@ -731,7 +728,7 @@ impl MemoryManager {
// see: https://github.com/rust-vmm/vm-memory/issues/174
loop {
let bytes_read = guest_memory
.read_volatile_from(
.read_from(
GuestAddress(range.gpa + offset),
&mut memory_file,
(range.length - offset) as usize,
@@ -1160,6 +1157,8 @@ impl MemoryManager {
},
start_of_platform_device_area,
PLATFORM_DEVICE_AREA_SIZE,
layout::MEM_32BIT_DEVICES_START,
layout::MEM_32BIT_DEVICES_SIZE,
#[cfg(target_arch = "x86_64")]
vec![GsiApic::new(
X86_64_IRQ_BASE,
@@ -2085,7 +2084,7 @@ impl MemoryManager {
return Ok(());
}
let coredump_file = dump_state.file.as_ref().unwrap();
let mut coredump_file = dump_state.file.as_ref().unwrap();
let guest_memory = self.guest_memory.memory();
let mut total_bytes: u64 = 0;
@@ -2094,9 +2093,9 @@ impl MemoryManager {
let mut offset: u64 = 0;
loop {
let bytes_written = guest_memory
.write_volatile_to(
.write_to(
GuestAddress(range.gpa + offset),
&mut coredump_file.as_fd(),
&mut coredump_file,
(range.length - offset) as usize,
)
.map_err(|e| GuestDebuggableError::Coredump(e.into()))?;
@@ -2119,7 +2118,7 @@ impl MemoryManager {
fd: &mut F,
) -> std::result::Result<(), MigratableError>
where
F: ReadVolatile,
F: Read,
{
let guest_memory = self.guest_memory();
let mem = guest_memory.memory();
@@ -2133,7 +2132,7 @@ impl MemoryManager {
// see: https://github.com/rust-vmm/vm-memory/issues/174
loop {
let bytes_read = mem
.read_volatile_from(
.read_from(
GuestAddress(range.gpa + offset),
fd,
(range.length - offset) as usize,
@@ -2601,7 +2600,7 @@ impl Transportable for MemoryManager {
// see: https://github.com/rust-vmm/vm-memory/issues/174
loop {
let bytes_written = guest_memory
.write_volatile_to(
.write_to(
GuestAddress(range.gpa + offset),
&mut memory_file,
(range.length - offset) as usize,

View File

@@ -7,7 +7,7 @@ use crate::coredump::GuestDebuggableError;
use crate::{config::VmConfig, vm::VmSnapshot};
use anyhow::anyhow;
use std::fs::File;
use std::io::Read;
use std::io::BufReader;
use std::path::PathBuf;
use vm_migration::{MigratableError, Snapshot};
@@ -49,14 +49,10 @@ pub fn recv_vm_config(source_url: &str) -> std::result::Result<VmConfig, Migrata
vm_config_path.push(SNAPSHOT_CONFIG_FILE);
// Try opening the snapshot file
let mut vm_config_file =
File::open(vm_config_path).map_err(|e| MigratableError::MigrateReceive(e.into()))?;
let mut bytes = Vec::new();
vm_config_file
.read_to_end(&mut bytes)
.map_err(|e| MigratableError::MigrateReceive(e.into()))?;
serde_json::from_slice(&bytes).map_err(|e| MigratableError::MigrateReceive(e.into()))
let vm_config_file =
File::open(vm_config_path).map_err(|e| MigratableError::MigrateSend(e.into()))?;
let vm_config_reader = BufReader::new(vm_config_file);
serde_json::from_reader(vm_config_reader).map_err(|e| MigratableError::MigrateReceive(e.into()))
}
pub fn recv_vm_state(source_url: &str) -> std::result::Result<Snapshot, MigratableError> {
@@ -65,14 +61,10 @@ pub fn recv_vm_state(source_url: &str) -> std::result::Result<Snapshot, Migratab
vm_state_path.push(SNAPSHOT_STATE_FILE);
// Try opening the snapshot file
let mut vm_state_file =
File::open(vm_state_path).map_err(|e| MigratableError::MigrateReceive(e.into()))?;
let mut bytes = Vec::new();
vm_state_file
.read_to_end(&mut bytes)
.map_err(|e| MigratableError::MigrateReceive(e.into()))?;
serde_json::from_slice(&bytes).map_err(|e| MigratableError::MigrateReceive(e.into()))
let vm_state_file =
File::open(vm_state_path).map_err(|e| MigratableError::MigrateSend(e.into()))?;
let vm_state_reader = BufReader::new(vm_state_file);
serde_json::from_reader(vm_state_reader).map_err(|e| MigratableError::MigrateReceive(e.into()))
}
pub fn get_vm_snapshot(snapshot: &Snapshot) -> std::result::Result<VmSnapshot, MigratableError> {

View File

@@ -38,14 +38,10 @@ pub(crate) struct PciSegment {
pub(crate) pci_irq_slots: [u8; 32],
// Device memory covered by this segment
pub(crate) start_of_mem32_area: u64,
pub(crate) end_of_mem32_area: u64,
pub(crate) start_of_device_area: u64,
pub(crate) end_of_device_area: u64,
pub(crate) start_of_mem64_area: u64,
pub(crate) end_of_mem64_area: u64,
pub(crate) mem32_allocator: Arc<Mutex<AddressAllocator>>,
pub(crate) mem64_allocator: Arc<Mutex<AddressAllocator>>,
pub(crate) allocator: Arc<Mutex<AddressAllocator>>,
}
impl PciSegment {
@@ -53,8 +49,7 @@ impl PciSegment {
id: u16,
numa_node: u32,
address_manager: &Arc<AddressManager>,
mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> {
let pci_root = PciRoot::new(None);
@@ -76,11 +71,8 @@ impl PciSegment {
)
.map_err(DeviceManagerError::BusError)?;
let start_of_mem32_area = mem32_allocator.lock().unwrap().base().0;
let end_of_mem32_area = mem32_allocator.lock().unwrap().end().0;
let start_of_mem64_area = mem64_allocator.lock().unwrap().base().0;
let end_of_mem64_area = mem64_allocator.lock().unwrap().end().0;
let start_of_device_area = allocator.lock().unwrap().base().0;
let end_of_device_area = allocator.lock().unwrap().end().0;
let segment = PciSegment {
id,
@@ -92,18 +84,15 @@ impl PciSegment {
pci_devices_down: 0,
#[cfg(target_arch = "x86_64")]
pci_config_io: None,
mem32_allocator,
mem64_allocator,
start_of_mem32_area,
end_of_mem32_area,
start_of_mem64_area,
end_of_mem64_area,
allocator,
start_of_device_area,
end_of_device_area,
pci_irq_slots: *pci_irq_slots,
};
info!(
"Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, mem32 area [0x{:x}-0x{:x}, mem64 area [0x{:x}-0x{:x}",
segment.id, segment.mmio_config_address, segment.start_of_mem32_area, segment.end_of_mem32_area, segment.start_of_mem64_area, segment.end_of_mem64_area
"Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, device area [0x{:x}-0x{:x}",
segment.id, segment.mmio_config_address, segment.start_of_device_area, segment.end_of_device_area
);
Ok(segment)
}
@@ -111,18 +100,10 @@ impl PciSegment {
#[cfg(target_arch = "x86_64")]
pub(crate) fn new_default_segment(
address_manager: &Arc<AddressManager>,
mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> {
let mut segment = Self::new(
0,
0,
address_manager,
mem32_allocator,
mem64_allocator,
pci_irq_slots,
)?;
let mut segment = Self::new(0, 0, address_manager, allocator, pci_irq_slots)?;
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&segment.pci_bus))));
address_manager
@@ -142,18 +123,10 @@ impl PciSegment {
#[cfg(target_arch = "aarch64")]
pub(crate) fn new_default_segment(
address_manager: &Arc<AddressManager>,
mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> {
Self::new(
0,
0,
address_manager,
mem32_allocator,
mem64_allocator,
pci_irq_slots,
)
Self::new(0, 0, address_manager, allocator, pci_irq_slots)
}
pub(crate) fn next_device_bdf(&self) -> DeviceManagerResult<PciBdf> {
@@ -367,7 +340,6 @@ impl Aml for PciSegment {
let pci_dsm = PciDsmMethod {};
pci_dsdt_inner_data.push(&pci_dsm);
#[allow(clippy::if_same_then_else)]
let crs = if self.id == 0 {
aml::Name::new(
"_CRS".into(),
@@ -375,23 +347,19 @@ impl Aml for PciSegment {
&aml::AddressSpace::new_bus_number(0x0u16, 0x0u16),
#[cfg(target_arch = "x86_64")]
&aml::IO::new(0xcf8, 0xcf8, 1, 0x8),
&aml::Memory32Fixed::new(
true,
self.mmio_config_address as u32,
layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT as u32,
),
&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
self.start_of_mem32_area,
self.end_of_mem32_area,
layout::MEM_32BIT_DEVICES_START.0 as u32,
(layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1)
as u32,
None,
),
&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
self.start_of_mem64_area,
self.end_of_mem64_area,
self.start_of_device_area,
self.end_of_device_area,
None,
),
#[cfg(target_arch = "x86_64")]
@@ -413,15 +381,8 @@ impl Aml for PciSegment {
&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
self.start_of_mem32_area,
self.end_of_mem32_area,
None,
),
&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
self.start_of_mem64_area,
self.end_of_mem64_area,
self.start_of_device_area,
self.end_of_device_area,
None,
),
]),

View File

@@ -25,8 +25,6 @@ use crate::device_manager::{DeviceManager, DeviceManagerError, PtyPair};
use crate::device_tree::DeviceTree;
#[cfg(feature = "guest_debug")]
use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload};
#[cfg(feature = "igvm")]
use crate::igvm::igvm_loader;
use crate::memory_manager::{
Error as MemoryManagerError, MemoryManager, MemoryManagerSnapshotData,
};
@@ -74,6 +72,8 @@ use std::collections::HashMap;
use std::convert::TryInto;
use std::fs::{File, OpenOptions};
use std::io::{self, Seek, SeekFrom, Write};
#[cfg(feature = "tdx")]
use std::mem;
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use std::mem::size_of;
use std::num::Wrapping;
@@ -86,10 +86,8 @@ use thiserror::Error;
use tracer::trace_scoped;
use vm_device::Bus;
#[cfg(feature = "tdx")]
use vm_memory::{Address, ByteValued, GuestMemoryRegion, ReadVolatile};
use vm_memory::{
Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, WriteVolatile,
};
use vm_memory::{Address, ByteValued, GuestMemory, GuestMemoryRegion};
use vm_memory::{Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::protocol::{Request, Response, Status};
use vm_migration::{
protocol::MemoryRangeTable, snapshot_from_id, Migratable, MigratableError, Pausable, Snapshot,
@@ -307,14 +305,6 @@ pub enum Error {
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
#[error("Error coredumping VM: {0:?}")]
Coredump(GuestDebuggableError),
#[cfg(feature = "igvm")]
#[error("Cannot open igvm file: {0}")]
IgvmFile(#[source] io::Error),
#[cfg(feature = "igvm")]
#[error("Cannot load the igvm into memory: {0}")]
IgvmLoad(#[source] igvm_loader::Error),
}
pub type Result<T> = result::Result<T, Error>;
@@ -491,7 +481,6 @@ impl Vm {
.validate()
.map_err(Error::ConfigValidation)?;
#[cfg(not(feature = "igvm"))]
let load_payload_handle = if snapshot.is_none() {
Self::load_payload_async(&memory_manager, &config)?
} else {
@@ -559,19 +548,6 @@ impl Vm {
)
.map_err(Error::CpuManager)?;
// Loading the igvm file is pushed down here because
// igvm parser needs cpu_manager to retrieve cpuid leaf.
// For the regular case, we can start loading early, but for
// igvm case we have to wait until cpu_manager is created.
// Currently, Microsoft Hypervisor does not provide any
// Hypervisor specific common cpuid, we need to call get_cpuid_values
// per cpuid through cpu_manager.
#[cfg(feature = "igvm")]
let load_payload_handle = if snapshot.is_none() {
Self::load_payload_async(&memory_manager, &config, &cpu_manager)?
} else {
None
};
// The initial TDX configuration must be done before the vCPUs are
// created
#[cfg(feature = "tdx")]
@@ -908,7 +884,7 @@ impl Vm {
}
fn load_initramfs(&mut self, guest_mem: &GuestMemoryMmap) -> Result<arch::InitramfsConfig> {
let initramfs = self.initramfs.as_mut().unwrap();
let mut initramfs = self.initramfs.as_ref().unwrap();
let size: usize = initramfs
.seek(SeekFrom::End(0))
.map_err(|_| Error::InitramfsLoad)?
@@ -921,7 +897,7 @@ impl Vm {
let address = GuestAddress(address);
guest_mem
.read_volatile_from(address, initramfs, size)
.read_from(address, &mut initramfs, size)
.map_err(|_| Error::InitramfsLoad)?;
info!("Initramfs loaded: address = 0x{:x}", address.0);
@@ -992,22 +968,6 @@ impl Vm {
Ok(EntryPoint { entry_addr })
}
#[cfg(feature = "igvm")]
fn load_igvm(
igvm: File,
memory_manager: Arc<Mutex<MemoryManager>>,
cpu_manager: Arc<Mutex<cpu::CpuManager>>,
) -> Result<EntryPoint> {
//TODO: see issue https://github.com/cloud-hypervisor/cloud-hypervisor/issues/5993
let res = igvm_loader::load_igvm(&igvm, memory_manager, cpu_manager, "")
.map_err(Error::IgvmLoad)?;
Ok(EntryPoint {
entry_addr: vm_memory::GuestAddress(res.vmsa.rip),
})
}
#[cfg(target_arch = "x86_64")]
fn load_kernel(
mut kernel: File,
@@ -1046,14 +1006,8 @@ impl Vm {
fn load_payload(
payload: &PayloadConfig,
memory_manager: Arc<Mutex<MemoryManager>>,
#[cfg(feature = "igvm")] cpu_manager: Arc<Mutex<cpu::CpuManager>>,
) -> Result<EntryPoint> {
trace_scoped!("load_payload");
#[cfg(feature = "igvm")]
if let Some(_igvm_file) = &payload.igvm {
let igvm = File::open(_igvm_file).map_err(Error::IgvmFile)?;
return Self::load_igvm(igvm, memory_manager, cpu_manager);
}
match (
&payload.firmware,
&payload.kernel,
@@ -1094,7 +1048,6 @@ impl Vm {
fn load_payload_async(
memory_manager: &Arc<Mutex<MemoryManager>>,
config: &Arc<Mutex<VmConfig>>,
#[cfg(feature = "igvm")] cpu_manager: &Arc<Mutex<cpu::CpuManager>>,
) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> {
// Kernel with TDX is loaded in a different manner
#[cfg(feature = "tdx")]
@@ -1110,19 +1063,10 @@ impl Vm {
.map(|payload| {
let memory_manager = memory_manager.clone();
let payload = payload.clone();
#[cfg(feature = "igvm")]
let cpu_manager = cpu_manager.clone();
std::thread::Builder::new()
.name("payload_loader".into())
.spawn(move || {
Self::load_payload(
&payload,
memory_manager,
#[cfg(feature = "igvm")]
cpu_manager,
)
})
.spawn(move || Self::load_payload(&payload, memory_manager))
.map_err(Error::KernelLoadThreadSpawn)
})
.transpose()
@@ -1218,9 +1162,9 @@ impl Vm {
let pci_space = PciSpaceInfo {
pci_segment_id: pci_segment.id,
mmio_config_address: pci_segment.mmio_config_address,
pci_device_space_start: pci_segment.start_of_mem64_area,
pci_device_space_size: pci_segment.end_of_mem64_area
- pci_segment.start_of_mem64_area
pci_device_space_start: pci_segment.start_of_device_area,
pci_device_space_size: pci_segment.end_of_device_area
- pci_segment.start_of_device_area
+ 1,
};
pci_space_info.push(pci_space);
@@ -1800,7 +1744,7 @@ impl Vm {
firmware_file
.seek(SeekFrom::Start(section.data_offset as u64))
.map_err(Error::LoadTdvf)?;
mem.read_volatile_from(
mem.read_from(
GuestAddress(section.address),
&mut firmware_file,
section.data_size as usize,
@@ -1822,8 +1766,13 @@ impl Vm {
.map_err(Error::LoadPayload)?;
let mut payload_header = linux_loader::bootparam::setup_header::default();
payload_file
.read_volatile(&mut payload_header.as_bytes())
payload_header
.as_bytes()
.read_from(
0,
payload_file,
mem::size_of::<linux_loader::bootparam::setup_header>(),
)
.unwrap();
if payload_header.header != 0x5372_6448 {
@@ -1837,7 +1786,7 @@ impl Vm {
}
payload_file.rewind().map_err(Error::LoadPayload)?;
mem.read_volatile_from(
mem.read_from(
GuestAddress(section.address),
payload_file,
payload_size as usize,
@@ -2180,7 +2129,7 @@ impl Vm {
fd: &mut F,
) -> std::result::Result<(), MigratableError>
where
F: WriteVolatile,
F: Write,
{
let guest_memory = self.memory_manager.lock().as_ref().unwrap().guest_memory();
let mem = guest_memory.memory();
@@ -2194,7 +2143,7 @@ impl Vm {
// see: https://github.com/rust-vmm/vm-memory/issues/174
loop {
let bytes_written = mem
.write_volatile_to(
.write_to(
GuestAddress(range.gpa + offset),
fd,
(range.length - offset) as usize,

View File

@@ -556,9 +556,6 @@ pub struct PayloadConfig {
pub cmdline: Option<String>,
#[serde(default)]
pub initramfs: Option<PathBuf>,
#[cfg(feature = "igvm")]
#[serde(default)]
pub igvm: Option<PathBuf>,
}
pub fn default_serial() -> ConsoleConfig {