mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c15de0118 | ||
|
|
ca9e20c27a | ||
|
|
028c3054ea | ||
|
|
82f1dcea3c | ||
|
|
bd6c898b1d | ||
|
|
98c1e21d92 | ||
|
|
7992997299 | ||
|
|
a1627d295a | ||
|
|
9278d565e2 | ||
|
|
f3c6f5c512 | ||
|
|
7c3c2ee0d6 | ||
|
|
19e45650a6 | ||
|
|
c3a4289cbb | ||
|
|
0886e79630 | ||
|
|
a40a0268bb | ||
|
|
339912a576 | ||
|
|
7ea0bf41be | ||
|
|
44f200d67d | ||
|
|
18d8c5669f | ||
|
|
57b7f35739 | ||
|
|
ed4537f4ae | ||
|
|
885412a99e | ||
|
|
128da81d83 | ||
|
|
0235bc4cee | ||
|
|
09a9cce95e | ||
|
|
ff818869dd | ||
|
|
c70f133b72 | ||
|
|
328cf39be1 | ||
|
|
64ad7657d1 | ||
|
|
cb6a53698c | ||
|
|
a91637067a | ||
|
|
88f3537b47 | ||
|
|
f557aadb67 | ||
|
|
ff6514572e | ||
|
|
11ec1e647c | ||
|
|
226816bb04 | ||
|
|
6e32c4531e | ||
|
|
9c994f882a | ||
|
|
b76d0e8b50 | ||
|
|
e151483f70 | ||
|
|
b904d666b0 | ||
|
|
0b99f96fc4 | ||
|
|
6d395c51db | ||
|
|
c4e8e653ac | ||
|
|
49e342314d | ||
|
|
0d9749282a | ||
|
|
83f3b34405 | ||
|
|
7bf0cc1ed5 | ||
|
|
fa09045f55 | ||
|
|
367201ed1e | ||
|
|
068470696f | ||
|
|
e2db476f6e | ||
|
|
07d1208dd5 | ||
|
|
4548de194d | ||
|
|
1b9ce69afa | ||
|
|
51548471fd | ||
|
|
70074ddf9f | ||
|
|
200cba0e20 | ||
|
|
5fd79571b7 | ||
|
|
3e1b0bc124 | ||
|
|
1632dbbf29 | ||
|
|
8d2e590886 | ||
|
|
e880aeed8d | ||
|
|
8bdf59bbee | ||
|
|
14edd6d9de | ||
|
|
01097aa130 | ||
|
|
9ca2c336f2 | ||
|
|
b1a1b2a622 | ||
|
|
556bda74a0 | ||
|
|
8db85eca1f | ||
|
|
b5766028a8 | ||
|
|
35757ec45a | ||
|
|
a51b48a095 | ||
|
|
d1ee623f0e | ||
|
|
a2752fe04f | ||
|
|
cc5dd8c297 | ||
|
|
2ed96cd3ed | ||
|
|
e02efe9ba0 | ||
|
|
654ac49bd6 | ||
|
|
8013e47856 | ||
|
|
7216d934de | ||
|
|
f45bbbfcac | ||
|
|
d87024a752 | ||
|
|
bb94dd18ee | ||
|
|
00e4f28e8f | ||
|
|
89661f6579 | ||
|
|
cd7eecc0b0 | ||
|
|
78ec651cbf | ||
|
|
3e54a586ce | ||
|
|
9d5c5a6410 | ||
|
|
8d072fef15 | ||
|
|
1dd1850747 | ||
|
|
0bead9ebe1 | ||
|
|
05a86d892e | ||
|
|
4d8dacec5e | ||
|
|
cc4422d58b | ||
|
|
239f422203 | ||
|
|
5636d91524 | ||
|
|
11c58870c4 | ||
|
|
b74907fa1b | ||
|
|
dbe67fca7f | ||
|
|
d3fc12b160 | ||
|
|
d73d3203dc | ||
|
|
16e1449f1e | ||
|
|
9dd1698556 | ||
|
|
d46dd4b31f | ||
|
|
0e75e7d079 | ||
|
|
be81fea46a | ||
|
|
cd010052f8 | ||
|
|
725bb8d038 | ||
|
|
ddfac7df0b | ||
|
|
6118359240 | ||
|
|
0a294bf2d7 | ||
|
|
baf10a45a9 | ||
|
|
c655e22e42 | ||
|
|
dd6ee3b39a | ||
|
|
8b651ec7ee | ||
|
|
5857d4851b | ||
|
|
0f63f8d001 | ||
|
|
2571e59438 | ||
|
|
d32e7fceb5 | ||
|
|
86655f4967 | ||
|
|
d9d1cdb0c6 | ||
|
|
ca155a790c |
3
.github/workflows/build.yaml
vendored
3
.github/workflows/build.yaml
vendored
@@ -51,6 +51,9 @@ jobs:
|
|||||||
- name: Build (mshv)
|
- name: Build (mshv)
|
||||||
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
|
- 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 (mshv + kvm)
|
- name: Build (mshv + kvm)
|
||||||
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
|
|||||||
17
.github/workflows/quality.yaml
vendored
17
.github/workflows/quality.yaml
vendored
@@ -101,6 +101,14 @@ jobs:
|
|||||||
command: clippy
|
command: clippy
|
||||||
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
|
- name: Clippy (sev_snp)
|
||||||
|
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 "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
- name: Clippy (kvm + tdx)
|
- name: Clippy (kvm + tdx)
|
||||||
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
@@ -111,3 +119,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Check build did not modify any files
|
- name: Check build did not modify any files
|
||||||
run: test -z "$(git status --porcelain)"
|
run: test -z "$(git status --porcelain)"
|
||||||
|
|
||||||
|
typos:
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
name: Typos / Spellcheck
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
# Executes "typos ."
|
||||||
|
- uses: crate-ci/typos@v1.16.11
|
||||||
|
|||||||
21
.typos.toml
Normal file
21
.typos.toml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Configuration for https://github.com/crate-ci/typos
|
||||||
|
|
||||||
|
[files]
|
||||||
|
extend-exclude = [
|
||||||
|
"hypervisor/src/kvm/x86_64/mod.rs",
|
||||||
|
"resources/linux-config-*",
|
||||||
|
]
|
||||||
|
|
||||||
|
[default.extend-words]
|
||||||
|
ba = "ba"
|
||||||
|
CLASSE = "CLASSE"
|
||||||
|
conectix = "conectix"
|
||||||
|
Dake = "Dake"
|
||||||
|
EXTINT = "EXTINT"
|
||||||
|
INOUT = "INOUT"
|
||||||
|
liness = "liness"
|
||||||
|
outout = "outout"
|
||||||
|
|
||||||
|
[default.extend-identifiers]
|
||||||
|
fo = "fo"
|
||||||
|
fpr = "fpr"
|
||||||
@@ -5,7 +5,7 @@ License](https://opensource.org/licenses/Apache-2.0) and the [BSD 3
|
|||||||
Clause](https://opensource.org/licenses/BSD-3-Clause) license. Individual files
|
Clause](https://opensource.org/licenses/BSD-3-Clause) license. Individual files
|
||||||
contain details of their licensing and changes to that file are under the same
|
contain details of their licensing and changes to that file are under the same
|
||||||
license unless the contribution changes the license of the file. When importing
|
license unless the contribution changes the license of the file. When importing
|
||||||
code from a third party project (e.g. Firecracker or CrosVM) please respect the
|
code from a third party project (e.g. Firecracker or crosvm) please respect the
|
||||||
license of those projects.
|
license of those projects.
|
||||||
|
|
||||||
New code should be under the [Apache v2
|
New code should be under the [Apache v2
|
||||||
|
|||||||
296
Cargo.lock
generated
296
Cargo.lock
generated
@@ -5,9 +5,9 @@ version = 3
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "acpi_tables"
|
name = "acpi_tables"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#05a609136387cc1cc9b499cee4320020325c263f"
|
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#1029d22777f07b04849234bbe756da34a6df2913"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy",
|
"zerocopy 0.6.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -36,9 +36,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.71"
|
version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -133,7 +133,7 @@ dependencies = [
|
|||||||
"async-lock",
|
"async-lock",
|
||||||
"async-task",
|
"async-task",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"fastrand",
|
"fastrand 1.9.0",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
@@ -164,7 +164,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"parking",
|
"parking",
|
||||||
"polling",
|
"polling",
|
||||||
"rustix",
|
"rustix 0.37.21",
|
||||||
"slab",
|
"slab",
|
||||||
"socket2",
|
"socket2",
|
||||||
"waker-fn",
|
"waker-fn",
|
||||||
@@ -192,7 +192,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"rustix",
|
"rustix 0.37.21",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
@@ -205,7 +205,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -216,13 +216,13 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.71"
|
version = "0.1.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
|
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -314,7 +314,7 @@ dependencies = [
|
|||||||
"async-lock",
|
"async-lock",
|
||||||
"async-task",
|
"async-task",
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"fastrand",
|
"fastrand 1.9.0",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
@@ -333,9 +333,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.79"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -345,7 +348,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "34.0.0"
|
version = "35.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -385,18 +388,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.8"
|
version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e"
|
checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -428,9 +431,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.1"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944"
|
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"darling_macro",
|
"darling_macro",
|
||||||
@@ -438,27 +441,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_core"
|
name = "darling_core"
|
||||||
version = "0.20.1"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb"
|
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.20.1"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
|
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -562,7 +565,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -621,6 +624,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"flume",
|
"flume",
|
||||||
"libc",
|
"libc",
|
||||||
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@@ -634,6 +638,12 @@ dependencies = [
|
|||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdt"
|
name = "fdt"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -713,7 +723,7 @@ version = "1.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand 1.9.0",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -730,7 +740,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -915,9 +925,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-uring"
|
name = "io-uring"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b7b36074613a723279637061b40db993208908a94f10ccb14436ce735bc0f57"
|
checksum = "141a0f4546a50b2ed637c7a6df0d7dff45c9f41523254996764461c8ae0d9424"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -934,13 +944,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.7"
|
version = "0.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"io-lifetimes",
|
"rustix 0.38.8",
|
||||||
"rustix",
|
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -987,9 +996,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.144"
|
version = "0.2.147"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libssh2-sys"
|
name = "libssh2-sys"
|
||||||
@@ -1007,9 +1016,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libz-sys"
|
name = "libz-sys"
|
||||||
version = "1.1.9"
|
version = "1.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db"
|
checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1019,9 +1028,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-loader"
|
name = "linux-loader"
|
||||||
version = "0.9.0"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d3adb7b28e189741eca3b1a4a27de0bf15e0907c9d4b0c74bd2d7d84ef72e08"
|
checksum = "1db6a725c8000971f83fa93ed7ee1b600e55a1471a2a653379d3c84f72effdcf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
@@ -1032,6 +1041,12 @@ version = "0.3.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
@@ -1075,7 +1090,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#b538bf89e50be83b6fa9ab1896727ff61e02fa13"
|
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#0d0fdcd50ea10c1b4777f9a958873fc848a5b7bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -1103,19 +1118,19 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-bindings"
|
name = "mshv-bindings"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#a45fbeb4a3930a2d17142e5687fe2f667c2df529"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#c5a60508595dc504da469b89102b8b49e91714a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
"zerocopy",
|
"zerocopy 0.7.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-ioctls"
|
name = "mshv-ioctls"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#a45fbeb4a3930a2d17142e5687fe2f667c2df529"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#c5a60508595dc504da469b89102b8b49e91714a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mshv-bindings",
|
"mshv-bindings",
|
||||||
@@ -1165,15 +1180,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"static_assertions",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1208,18 +1222,18 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-src"
|
name = "openssl-src"
|
||||||
version = "111.26.0+1.1.1u"
|
version = "300.1.3+3.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
|
checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.90"
|
version = "0.9.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
|
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1361,14 +1375,14 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
@@ -1384,9 +1398,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet"
|
name = "pnet"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd959a8268165518e2bf5546ba84c7b3222744435616381df3c456fe8d983576"
|
checksum = "130c5b738eeda2dc5796fe2671e49027e6935e817ab51b930a36ec9e6a206a64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -1398,18 +1412,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_base"
|
name = "pnet_base"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "872e46346144ebf35219ccaa64b1dffacd9c6f188cd7d012bd6977a2a838f42e"
|
checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"no-std-net",
|
"no-std-net",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_datalink"
|
name = "pnet_datalink"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c302da22118d2793c312a35fb3da6846cb0fab6c3ad53fd67e37809b06cdafce"
|
checksum = "ad5854abf0067ebbd3967f7d45ebc8976ff577ff0c7bd101c4973ae3c70f98fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1420,30 +1434,30 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros"
|
name = "pnet_macros"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a780e80005c2e463ec25a6e9f928630049a10b43945fea83207207d4a7606f4"
|
checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"syn 1.0.109",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros_support"
|
name = "pnet_macros_support"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6d932134f32efd7834eb8b16d42418dac87086347d1bc7d142370ef078582bc"
|
checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_packet"
|
name = "pnet_packet"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8bde678bbd85cb1c2d99dc9fc596e57f03aa725f84f3168b0eaf33eeccb41706"
|
checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -1453,9 +1467,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_sys"
|
name = "pnet_sys"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "faf7a58b2803d818a374be9278a1fe8f88fce14b936afbe225000cfcd9c73f16"
|
checksum = "417c0becd1b573f6d544f73671070b039051e5ad819cc64aa96377b536128d00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -1463,9 +1477,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_transport"
|
name = "pnet_transport"
|
||||||
version = "0.33.0"
|
version = "0.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "813d1c0e4defbe7ee22f6fe1755f122b77bfb5abe77145b1b5baaf463cab9249"
|
checksum = "2637e14d7de974ee2f74393afccbc8704f3e54e6eb31488715e72481d1662cc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -1507,18 +1521,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.63"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.29"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -1605,9 +1619,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.3.3"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -1616,9 +1630,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.7.4"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remain"
|
name = "remain"
|
||||||
@@ -1628,7 +1642,7 @@ checksum = "bce3a7139d2ee67d07538ee5dba997364fbc243e7e7143e96eb830c74bfaa082"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1662,7 +1676,20 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys 0.3.8",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.3.3",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.4.5",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1689,35 +1716,35 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.17"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.164"
|
version = "1.0.168"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
|
checksum = "d614f89548720367ded108b3c843be93f3a341e22d5674ca0dd5cd57f34926af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.164"
|
version = "1.0.168"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
|
checksum = "d4fe589678c688e44177da4f27152ee2d190757271dc7f1d5b6b9f68d869d641"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.96"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -1732,7 +1759,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1754,7 +1781,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1802,9 +1829,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.10.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@@ -1862,9 +1889,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.23"
|
version = "2.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737"
|
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1883,15 +1910,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.5.0"
|
version = "3.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
|
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand",
|
"fastrand 2.0.0",
|
||||||
"redox_syscall 0.3.5",
|
"redox_syscall 0.3.5",
|
||||||
"rustix",
|
"rustix 0.38.8",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1935,7 +1962,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2005,7 +2032,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2090,7 +2117,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -2098,7 +2125,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
@@ -2116,7 +2143,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio_user"
|
name = "vfio_user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#eef6bec4d421f08ed1688fe67c5ea33aabbf5069"
|
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#2d96b90a7279547356ad8f83aaa3115ad5497302"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2132,8 +2159,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.7.0"
|
version = "0.8.1"
|
||||||
source = "git+https://github.com/rust-vmm/vhost?branch=main#bdc6f2ab2b3dbd3b9574100ac641a2f8e9667400"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61957aeb36daf0b00b87fff9c10dd28a161bd35ab157553d340d183b3d8756e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2143,9 +2171,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost-user-backend"
|
name = "vhost-user-backend"
|
||||||
version = "0.9.0"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5d3b7affe04f61d19b03c5db823287855789b687218fec139699a0c7f7f2790"
|
checksum = "ab069cdedaf18a0673766eb0a07a0f4ee3ed1b8e17fbfe4aafe5b988e2de1d01"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
@@ -2195,9 +2223,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-bindings"
|
name = "virtio-bindings"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b9084faf91b9aa9676ae2cac8f1432df2839d9566e6f19f29dbc13a8b831dff"
|
checksum = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-devices"
|
name = "virtio-devices"
|
||||||
@@ -2235,9 +2263,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-queue"
|
name = "virtio-queue"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91aebb1df33db33cbf04d4c2445e4f78d0b0c8e65acfd16a4ee95ef63ca252f8"
|
checksum = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
@@ -2274,12 +2302,13 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#77212bd0d62913e445c
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d6ea57fe00f9086c59eeeb68e102dd611686bc3c28520fa465996d4d4bdce07"
|
checksum = "9dc276f0d00c17b9aeb584da0f1e1c673df0d183cc2539e3636ec8cbc5eae99b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
|
"thiserror",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2316,9 +2345,11 @@ dependencies = [
|
|||||||
"bitflags 2.3.3",
|
"bitflags 2.3.3",
|
||||||
"block",
|
"block",
|
||||||
"blocking",
|
"blocking",
|
||||||
|
"cfg-if",
|
||||||
"devices",
|
"devices",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
|
"flume",
|
||||||
"futures",
|
"futures",
|
||||||
"gdbstub",
|
"gdbstub",
|
||||||
"gdbstub_arch",
|
"gdbstub_arch",
|
||||||
@@ -2352,7 +2383,7 @@ dependencies = [
|
|||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
"zbus",
|
"zbus",
|
||||||
"zerocopy",
|
"zerocopy 0.6.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2409,7 +2440,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2431,7 +2462,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.23",
|
"syn 2.0.31",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@@ -2697,7 +2728,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive 0.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f00a66029e63d181fa590cc5694cf2afbc0974a4604824e80017b1789f99c07"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive 0.7.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2711,6 +2752,17 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9c682f46403e5d567cb27b79f6279c145759528ba9450fe371f43b921b452bd"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.31",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "3.15.0"
|
version = "3.15.0"
|
||||||
|
|||||||
14
Cargo.toml
14
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "34.0.0"
|
version = "35.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "cloud-hypervisor"
|
default-run = "cloud-hypervisor"
|
||||||
@@ -29,25 +29,25 @@ strip = false
|
|||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
api_client = { path = "api_client" }
|
api_client = { path = "api_client" }
|
||||||
argh = "0.1.9"
|
argh = "0.1.9"
|
||||||
dhat = { version = "0.3.2", optional = true }
|
dhat = { version = "0.3.2", optional = true }
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
event_monitor = { path = "event_monitor" }
|
event_monitor = { path = "event_monitor" }
|
||||||
hypervisor = { path = "hypervisor" }
|
hypervisor = { path = "hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = { version = "0.4.17", features = ["std"] }
|
log = { version = "0.4.17", features = ["std"] }
|
||||||
option_parser = { path = "option_parser" }
|
option_parser = { path = "option_parser" }
|
||||||
seccompiler = "0.3.0"
|
seccompiler = "0.3.0"
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
signal-hook = "0.3.17"
|
signal-hook = "0.3.17"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
tpm = { path = "tpm"}
|
tpm = { path = "tpm"}
|
||||||
tracer = { path = "tracer" }
|
tracer = { path = "tracer" }
|
||||||
vmm = { path = "vmm" }
|
vmm = { path = "vmm" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
zbus = { version = "3.11.1", optional = true }
|
zbus = { version = "3.11.1", optional = true }
|
||||||
|
|
||||||
# List of patched crates
|
# List of patched crates
|
||||||
@@ -55,13 +55,12 @@ zbus = { version = "3.11.1", optional = true }
|
|||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
|
||||||
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
|
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
|
||||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
||||||
vhost = { git = "https://github.com/rust-vmm/vhost", branch = "main" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dirs = "5.0.0"
|
dirs = "5.0.0"
|
||||||
net_util = { path = "net_util" }
|
net_util = { path = "net_util" }
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
test_infra = { path = "test_infra" }
|
test_infra = { path = "test_infra" }
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|
||||||
@@ -73,6 +72,7 @@ guest_debug = ["vmm/guest_debug"]
|
|||||||
io_uring = ["vmm/io_uring"]
|
io_uring = ["vmm/io_uring"]
|
||||||
kvm = ["vmm/kvm"]
|
kvm = ["vmm/kvm"]
|
||||||
mshv = ["vmm/mshv"]
|
mshv = ["vmm/mshv"]
|
||||||
|
sev_snp = ["vmm/sev_snp", "mshv"]
|
||||||
tdx = ["vmm/tdx"]
|
tdx = ["vmm/tdx"]
|
||||||
tracing = ["vmm/tracing", "tracer/tracing"]
|
tracing = ["vmm/tracing", "tracer/tracing"]
|
||||||
|
|
||||||
|
|||||||
292
Jenkinsfile
vendored
292
Jenkinsfile
vendored
@@ -22,7 +22,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
runWorkers = false
|
runWorkers = false
|
||||||
echo 'No changes requring a build'
|
echo 'No changes requiring a build'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh 'sudo modprobe openvswitch'
|
sh 'sudo modprobe openvswitch'
|
||||||
sh 'scripts/dev_cli.sh tests --integration'
|
sh 'scripts/dev_cli.sh tests --integration -- -- --skip common_parallel::test_vfio'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Run live-migration integration tests') {
|
stage('Run live-migration integration tests') {
|
||||||
@@ -151,7 +151,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh 'sudo modprobe openvswitch'
|
sh 'sudo modprobe openvswitch'
|
||||||
sh 'scripts/dev_cli.sh tests --integration-live-migration --integration -- -- --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog_local'
|
sh 'scripts/dev_cli.sh tests --integration-live-migration'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Run integration tests for musl') {
|
stage('Run integration tests for musl') {
|
||||||
@@ -160,7 +160,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh 'sudo modprobe openvswitch'
|
sh 'sudo modprobe openvswitch'
|
||||||
sh 'scripts/dev_cli.sh tests --integration --libc musl'
|
sh 'scripts/dev_cli.sh tests --integration --libc musl -- -- --skip common_parallel::test_vfio'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Run live-migration integration tests for musl') {
|
stage('Run live-migration integration tests for musl') {
|
||||||
@@ -169,7 +169,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh 'sudo modprobe openvswitch'
|
sh 'sudo modprobe openvswitch'
|
||||||
sh 'scripts/dev_cli.sh tests --integration-live-migration --libc musl -- -- --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog_local'
|
sh 'scripts/dev_cli.sh tests --integration-live-migration --libc musl'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
stage('Install azure-cli') {
|
stage('Install azure-cli') {
|
||||||
steps {
|
steps {
|
||||||
installAzureCli('bionic', 'arm64')
|
installAzureCli('focal', 'arm64')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Download Windows image') {
|
stage('Download Windows image') {
|
||||||
@@ -295,146 +295,146 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stage('Worker build - Metrics') {
|
stage('Worker build - Metrics') {
|
||||||
// agent { node { label 'jammy-metrics' } }
|
agent { node { label 'jammy-metrics' } }
|
||||||
// when {
|
when {
|
||||||
// branch 'main'
|
branch 'main'
|
||||||
// beforeAgent true
|
beforeAgent true
|
||||||
// expression {
|
expression {
|
||||||
// return runWorkers
|
return runWorkers
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// environment {
|
environment {
|
||||||
// METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
|
METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
|
||||||
// }
|
}
|
||||||
// stages {
|
stages {
|
||||||
// stage('Checkout') {
|
stage('Checkout') {
|
||||||
// steps {
|
steps {
|
||||||
// checkout scm
|
checkout scm
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run metrics tests') {
|
stage('Run metrics tests') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
|
sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Upload metrics report') {
|
stage('Upload metrics report') {
|
||||||
// steps {
|
steps {
|
||||||
// sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
|
sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Worker build - Rate Limiter') {
|
stage('Worker build - Rate Limiter') {
|
||||||
// agent { node { label 'focal-metrics' } }
|
agent { node { label 'focal-metrics' } }
|
||||||
// when {
|
when {
|
||||||
// branch 'main'
|
branch 'main'
|
||||||
// beforeAgent true
|
beforeAgent true
|
||||||
// expression {
|
expression {
|
||||||
// return runWorkers
|
return runWorkers
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stages {
|
stages {
|
||||||
// stage('Checkout') {
|
stage('Checkout') {
|
||||||
// steps {
|
steps {
|
||||||
// checkout scm
|
checkout scm
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run rate-limiter integration tests') {
|
stage('Run rate-limiter integration tests') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 10, unit: 'MINUTES')
|
timeout(time: 10, unit: 'MINUTES')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
|
sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Worker build - SGX') {
|
stage('Worker build - SGX') {
|
||||||
// agent { node { label 'jammy-sgx' } }
|
agent { node { label 'jammy-sgx' } }
|
||||||
// when {
|
when {
|
||||||
// beforeAgent true
|
beforeAgent true
|
||||||
// allOf {
|
allOf {
|
||||||
// branch 'main'
|
branch 'main'
|
||||||
// expression {
|
expression {
|
||||||
// return runWorkers
|
return runWorkers
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stages {
|
stages {
|
||||||
// stage('Checkout') {
|
stage('Checkout') {
|
||||||
// steps {
|
steps {
|
||||||
// checkout scm
|
checkout scm
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run SGX integration tests') {
|
stage('Run SGX integration tests') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --integration-sgx'
|
sh 'scripts/dev_cli.sh tests --integration-sgx'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run SGX integration tests for musl') {
|
stage('Run SGX integration tests for musl') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --integration-sgx --libc musl'
|
sh 'scripts/dev_cli.sh tests --integration-sgx --libc musl'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// post {
|
post {
|
||||||
// always {
|
always {
|
||||||
// sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
||||||
// deleteDir()
|
deleteDir()
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Worker build - VFIO') {
|
stage('Worker build - VFIO') {
|
||||||
// agent { node { label 'jammy-vfio' } }
|
agent { node { label 'jammy-vfio' } }
|
||||||
// when {
|
when {
|
||||||
// beforeAgent true
|
beforeAgent true
|
||||||
// allOf {
|
allOf {
|
||||||
// branch 'main'
|
branch 'main'
|
||||||
// expression {
|
expression {
|
||||||
// return runWorkers
|
return runWorkers
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stages {
|
stages {
|
||||||
// stage('Checkout') {
|
stage('Checkout') {
|
||||||
// steps {
|
steps {
|
||||||
// checkout scm
|
checkout scm
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run VFIO integration tests') {
|
stage('Run VFIO integration tests') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --integration-vfio'
|
sh 'scripts/dev_cli.sh tests --integration-vfio'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// stage('Run VFIO integration tests for musl') {
|
stage('Run VFIO integration tests for musl') {
|
||||||
// options {
|
options {
|
||||||
// timeout(time: 1, unit: 'HOURS')
|
timeout(time: 1, unit: 'HOURS')
|
||||||
// }
|
}
|
||||||
// steps {
|
steps {
|
||||||
// sh 'scripts/dev_cli.sh tests --integration-vfio --libc musl'
|
sh 'scripts/dev_cli.sh tests --integration-vfio --libc musl'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// post {
|
post {
|
||||||
// always {
|
always {
|
||||||
// sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
||||||
// deleteDir()
|
deleteDir()
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,22 @@ edition = "2021"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
sev_snp = []
|
||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
linux-loader = { version = "0.9.0", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
uuid = "1.3.4"
|
uuid = "1.3.4"
|
||||||
versionize = "0.1.10"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-bitmap"] }
|
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ pub enum CacheLevel {
|
|||||||
L3 = 3,
|
L3 = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: CACHE SIZE file directory example,
|
/// NOTE: cache size file directory example,
|
||||||
/// "/sys/devices/system/cpu/cpu0/cache/index0/size".
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/size".
|
||||||
pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
|
pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
|
||||||
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
@@ -111,7 +111,7 @@ pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
|
|||||||
|
|
||||||
let file_path = Path::new(&file_directory);
|
let file_path = Path::new(&file_directory);
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
error!("File: {} not exist.", file_directory);
|
warn!("File: {} does not exist.", file_directory);
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
info!("File: {} exist.", file_directory);
|
info!("File: {} exist.", file_directory);
|
||||||
@@ -132,7 +132,7 @@ pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: CACHE COHERENCY LINE SIZE file directory example,
|
/// NOTE: coherency_line_size file directory example,
|
||||||
/// "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size".
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size".
|
||||||
pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
|
pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
|
||||||
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
@@ -145,7 +145,7 @@ pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
|
|||||||
|
|
||||||
let file_path = Path::new(&file_directory);
|
let file_path = Path::new(&file_directory);
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
error!("File: {} not exist.", file_directory);
|
warn!("File: {} does not exist.", file_directory);
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
info!("File: {} exist.", file_directory);
|
info!("File: {} exist.", file_directory);
|
||||||
@@ -155,7 +155,7 @@ pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: CACHE NUMBER OF SETS file directory example,
|
/// NOTE: number_of_sets file directory example,
|
||||||
/// "/sys/devices/system/cpu/cpu0/cache/index0/number_of_sets".
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/number_of_sets".
|
||||||
pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
|
pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
|
||||||
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
@@ -168,7 +168,7 @@ pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
|
|||||||
|
|
||||||
let file_path = Path::new(&file_directory);
|
let file_path = Path::new(&file_directory);
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
error!("File: {} not exist.", file_directory);
|
warn!("File: {} does not exist.", file_directory);
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
info!("File: {} exist.", file_directory);
|
info!("File: {} exist.", file_directory);
|
||||||
@@ -178,6 +178,41 @@ pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NOTE: shared_cpu_list file directory example,
|
||||||
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list".
|
||||||
|
pub fn get_cache_shared(cache_level: CacheLevel) -> bool {
|
||||||
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
|
let mut result = true;
|
||||||
|
|
||||||
|
match cache_level {
|
||||||
|
CacheLevel::L1D | CacheLevel::L1I => result = false,
|
||||||
|
CacheLevel::L2 => file_directory += "/index2/shared_cpu_list",
|
||||||
|
CacheLevel::L3 => file_directory += "/index3/shared_cpu_list",
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = Path::new(&file_directory);
|
||||||
|
if !file_path.exists() {
|
||||||
|
warn!("File: {} does not exist.", file_directory);
|
||||||
|
result = false;
|
||||||
|
} else {
|
||||||
|
info!("File: {} exist.", file_directory);
|
||||||
|
|
||||||
|
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
|
||||||
|
let src = src.trim();
|
||||||
|
if src.is_empty() {
|
||||||
|
result = false;
|
||||||
|
} else {
|
||||||
|
result = src.contains('-') || src.contains(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates the flattened device tree for this aarch64 VM.
|
/// Creates the flattened device tree for this aarch64 VM.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||||
@@ -255,6 +290,8 @@ fn create_cpu_nodes(
|
|||||||
fdt.property_u32("#size-cells", 0x0)?;
|
fdt.property_u32("#size-cells", 0x0)?;
|
||||||
|
|
||||||
let num_cpus = vcpu_mpidr.len();
|
let num_cpus = vcpu_mpidr.len();
|
||||||
|
let (threads_per_core, cores_per_package, packages) = vcpu_topology.unwrap_or((1, 1, 1));
|
||||||
|
let max_cpus: u32 = (threads_per_core * cores_per_package * packages).into();
|
||||||
|
|
||||||
// Add cache info.
|
// Add cache info.
|
||||||
// L1 Data Cache Info.
|
// L1 Data Cache Info.
|
||||||
@@ -277,10 +314,14 @@ fn create_cpu_nodes(
|
|||||||
let mut l3_cache_line_size: u32 = 0;
|
let mut l3_cache_line_size: u32 = 0;
|
||||||
let mut l3_cache_sets: u32 = 0;
|
let mut l3_cache_sets: u32 = 0;
|
||||||
|
|
||||||
|
// Cache Shared Info.
|
||||||
|
let mut l2_cache_shared: bool = false;
|
||||||
|
let mut l3_cache_shared: bool = false;
|
||||||
|
|
||||||
let cache_path = Path::new("/sys/devices/system/cpu/cpu0/cache");
|
let cache_path = Path::new("/sys/devices/system/cpu/cpu0/cache");
|
||||||
let cache_exist: bool = cache_path.exists();
|
let cache_exist: bool = cache_path.exists();
|
||||||
if !cache_exist {
|
if !cache_exist {
|
||||||
error!("cache sysfs system does not exist.");
|
warn!("cache sysfs system does not exist.");
|
||||||
} else {
|
} else {
|
||||||
info!("cache sysfs system exists.");
|
info!("cache sysfs system exists.");
|
||||||
// L1 Data Cache Info.
|
// L1 Data Cache Info.
|
||||||
@@ -302,6 +343,14 @@ fn create_cpu_nodes(
|
|||||||
l3_cache_size = get_cache_size(CacheLevel::L3);
|
l3_cache_size = get_cache_size(CacheLevel::L3);
|
||||||
l3_cache_line_size = get_cache_coherency_line_size(CacheLevel::L3);
|
l3_cache_line_size = get_cache_coherency_line_size(CacheLevel::L3);
|
||||||
l3_cache_sets = get_cache_number_of_sets(CacheLevel::L3);
|
l3_cache_sets = get_cache_number_of_sets(CacheLevel::L3);
|
||||||
|
|
||||||
|
// Cache Shared Info.
|
||||||
|
if l2_cache_size != 0 {
|
||||||
|
l2_cache_shared = get_cache_shared(CacheLevel::L2);
|
||||||
|
}
|
||||||
|
if l3_cache_size != 0 {
|
||||||
|
l3_cache_shared = get_cache_shared(CacheLevel::L3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cpu_id, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
|
for (cpu_id, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
|
||||||
@@ -318,21 +367,6 @@ fn create_cpu_nodes(
|
|||||||
fdt.property_u32("reg", (mpidr & 0x7FFFFF) as u32)?;
|
fdt.property_u32("reg", (mpidr & 0x7FFFFF) as u32)?;
|
||||||
fdt.property_u32("phandle", cpu_id as u32 + FIRST_VCPU_PHANDLE)?;
|
fdt.property_u32("phandle", cpu_id as u32 + FIRST_VCPU_PHANDLE)?;
|
||||||
|
|
||||||
if cache_exist && l1_d_cache_size != 0 && l1_i_cache_size != 0 {
|
|
||||||
// Add cache info.
|
|
||||||
fdt.property_u32("d-cache-size", l1_d_cache_size)?;
|
|
||||||
fdt.property_u32("d-cache-line-size", l1_d_cache_line_size)?;
|
|
||||||
fdt.property_u32("d-cache-sets", l1_d_cache_sets)?;
|
|
||||||
|
|
||||||
fdt.property_u32("i-cache-size", l1_i_cache_size)?;
|
|
||||||
fdt.property_u32("i-cache-line-size", l1_i_cache_line_size)?;
|
|
||||||
fdt.property_u32("i-cache-sets", l1_i_cache_sets)?;
|
|
||||||
|
|
||||||
if l2_cache_size != 0 {
|
|
||||||
fdt.property_u32("next-level-cache", L2_CACHE_PHANDLE)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add `numa-node-id` property if there is any numa config.
|
// Add `numa-node-id` property if there is any numa config.
|
||||||
if numa_nodes.len() > 1 {
|
if numa_nodes.len() > 1 {
|
||||||
for numa_node_idx in 0..numa_nodes.len() {
|
for numa_node_idx in 0..numa_nodes.len() {
|
||||||
@@ -343,37 +377,89 @@ fn create_cpu_nodes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cache_exist && l1_d_cache_size != 0 && l1_i_cache_size != 0 {
|
||||||
|
// Add cache info.
|
||||||
|
fdt.property_u32("d-cache-size", l1_d_cache_size)?;
|
||||||
|
fdt.property_u32("d-cache-line-size", l1_d_cache_line_size)?;
|
||||||
|
fdt.property_u32("d-cache-sets", l1_d_cache_sets)?;
|
||||||
|
|
||||||
|
fdt.property_u32("i-cache-size", l1_i_cache_size)?;
|
||||||
|
fdt.property_u32("i-cache-line-size", l1_i_cache_line_size)?;
|
||||||
|
fdt.property_u32("i-cache-sets", l1_i_cache_sets)?;
|
||||||
|
|
||||||
|
if l2_cache_size != 0 && !l2_cache_shared {
|
||||||
|
fdt.property_u32(
|
||||||
|
"next-level-cache",
|
||||||
|
cpu_id as u32 + max_cpus + FIRST_VCPU_PHANDLE + L2_CACHE_PHANDLE,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let l2_cache_name = "l2-cache0";
|
||||||
|
let l2_cache_node = fdt.begin_node(l2_cache_name)?;
|
||||||
|
// PHANDLE is used to mark device node, and PHANDLE is unique. To avoid phandle
|
||||||
|
// conflicts with other device nodes, consider the previous CPU PHANDLE, so the
|
||||||
|
// CPU L2 cache PHANDLE must start from the largest CPU PHANDLE plus 1.
|
||||||
|
fdt.property_u32(
|
||||||
|
"phandle",
|
||||||
|
cpu_id as u32 + max_cpus + FIRST_VCPU_PHANDLE + L2_CACHE_PHANDLE,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
fdt.property_string("compatible", "cache")?;
|
||||||
|
fdt.property_u32("cache-size", l2_cache_size)?;
|
||||||
|
fdt.property_u32("cache-line-size", l2_cache_line_size)?;
|
||||||
|
fdt.property_u32("cache-sets", l2_cache_sets)?;
|
||||||
|
fdt.property_u32("cache-level", 2)?;
|
||||||
|
|
||||||
|
if l3_cache_size != 0 && l3_cache_shared {
|
||||||
|
let package_id: u32 = cpu_id as u32 / cores_per_package as u32;
|
||||||
|
fdt.property_u32(
|
||||||
|
"next-level-cache",
|
||||||
|
package_id
|
||||||
|
+ num_cpus as u32
|
||||||
|
+ max_cpus
|
||||||
|
+ FIRST_VCPU_PHANDLE
|
||||||
|
+ L2_CACHE_PHANDLE
|
||||||
|
+ L3_CACHE_PHANDLE,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt.end_node(l2_cache_node)?;
|
||||||
|
}
|
||||||
|
if l2_cache_size != 0 && l2_cache_shared {
|
||||||
|
warn!("L2 cache shared with other cpus");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fdt.end_node(cpu_node)?;
|
fdt.end_node(cpu_node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if cache_exist && l2_cache_size != 0 {
|
if cache_exist && l3_cache_size != 0 && !l2_cache_shared && l3_cache_shared {
|
||||||
let l2_cache_name = "l2-cache0";
|
let mut i: u32 = 0;
|
||||||
let l2_cache_node = fdt.begin_node(l2_cache_name)?;
|
while i < packages.into() {
|
||||||
fdt.property_u32("phandle", L2_CACHE_PHANDLE)?;
|
let l3_cache_name = "l3-cache0";
|
||||||
fdt.property_string("compatible", "cache")?;
|
let l3_cache_node = fdt.begin_node(l3_cache_name)?;
|
||||||
fdt.property_u32("cache-size", l2_cache_size)?;
|
// ARM L3 cache is generally shared within the package (socket), so the
|
||||||
fdt.property_u32("cache-line-size", l2_cache_line_size)?;
|
// L3 cache node pointed to by the CPU in the package has the same L3
|
||||||
fdt.property_u32("cache-sets", l2_cache_sets)?;
|
// cache PHANDLE. The L3 cache phandle must start from the largest L2
|
||||||
fdt.property_u32("cache-level", 2)?;
|
// cache PHANDLE plus 1 to avoid duplication.
|
||||||
|
fdt.property_u32(
|
||||||
|
"phandle",
|
||||||
|
i + num_cpus as u32
|
||||||
|
+ max_cpus
|
||||||
|
+ FIRST_VCPU_PHANDLE
|
||||||
|
+ L2_CACHE_PHANDLE
|
||||||
|
+ L3_CACHE_PHANDLE,
|
||||||
|
)?;
|
||||||
|
|
||||||
if l3_cache_size != 0 {
|
fdt.property_string("compatible", "cache")?;
|
||||||
fdt.property_u32("next-level-cache", L3_CACHE_PHANDLE)?;
|
fdt.property_null("cache-unified")?;
|
||||||
|
fdt.property_u32("cache-size", l3_cache_size)?;
|
||||||
|
fdt.property_u32("cache-line-size", l3_cache_line_size)?;
|
||||||
|
fdt.property_u32("cache-sets", l3_cache_sets)?;
|
||||||
|
fdt.property_u32("cache-level", 3)?;
|
||||||
|
fdt.end_node(l3_cache_node)?;
|
||||||
|
|
||||||
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt.end_node(l2_cache_node)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if cache_exist && l3_cache_size != 0 {
|
|
||||||
let l3_cache_name = "l3-cache0";
|
|
||||||
let l3_cache_node = fdt.begin_node(l3_cache_name)?;
|
|
||||||
fdt.property_u32("phandle", L3_CACHE_PHANDLE)?;
|
|
||||||
fdt.property_string("compatible", "cache")?;
|
|
||||||
fdt.property_null("cache-unified")?;
|
|
||||||
fdt.property_u32("cache-size", l3_cache_size)?;
|
|
||||||
fdt.property_u32("cache-line-size", l3_cache_line_size)?;
|
|
||||||
fdt.property_u32("cache-sets", l3_cache_sets)?;
|
|
||||||
fdt.property_u32("cache-level", 3)?;
|
|
||||||
fdt.end_node(l3_cache_node)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(topology) = vcpu_topology {
|
if let Some(topology) = vcpu_topology {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub const _NSIG: i32 = 65;
|
|||||||
/// is to be used to configure the guest initial state.
|
/// is to be used to configure the guest initial state.
|
||||||
pub struct EntryPoint {
|
pub struct EntryPoint {
|
||||||
/// Address in guest memory where the guest must start execution
|
/// Address in guest memory where the guest must start execution
|
||||||
pub entry_addr: Option<GuestAddress>,
|
pub entry_addr: GuestAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
const E820_RAM: u32 = 1;
|
const E820_RAM: u32 = 1;
|
||||||
@@ -811,12 +811,10 @@ pub fn configure_vcpu(
|
|||||||
|
|
||||||
regs::setup_msrs(vcpu).map_err(Error::MsrsConfiguration)?;
|
regs::setup_msrs(vcpu).map_err(Error::MsrsConfiguration)?;
|
||||||
if let Some((kernel_entry_point, guest_memory)) = boot_setup {
|
if let Some((kernel_entry_point, guest_memory)) = boot_setup {
|
||||||
if let Some(entry_addr) = kernel_entry_point.entry_addr {
|
regs::setup_regs(vcpu, kernel_entry_point.entry_addr.raw_value())
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
.map_err(Error::RegsConfiguration)?;
|
||||||
regs::setup_regs(vcpu, entry_addr.raw_value()).map_err(Error::RegsConfiguration)?;
|
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
||||||
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
regs::setup_sregs(&guest_memory.memory(), vcpu).map_err(Error::SregsConfiguration)?;
|
||||||
regs::setup_sregs(&guest_memory.memory(), vcpu).map_err(Error::SregsConfiguration)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
interrupts::set_lint(vcpu).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
interrupts::set_lint(vcpu).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ fn tdvf_descriptor_offset(file: &mut File) -> Result<(SeekFrom, bool), TdvfError
|
|||||||
// We start after the footer GUID and the table length.
|
// We start after the footer GUID and the table length.
|
||||||
let mut offset = table_size - 18;
|
let mut offset = table_size - 18;
|
||||||
|
|
||||||
debug!("Parsing GUIDed structure");
|
debug!("Parsing GUID structure");
|
||||||
while offset >= 18 {
|
while offset >= 18 {
|
||||||
let entry_uuid = Uuid::from_slice_le(&table[offset - 16..offset])
|
let entry_uuid = Uuid::from_slice_le(&table[offset - 16..offset])
|
||||||
.map_err(TdvfError::UuidCreation)?;
|
.map_err(TdvfError::UuidCreation)?;
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ io_uring = ["dep:io-uring"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
crc32c = "0.6.3"
|
crc32c = "0.6.4"
|
||||||
io-uring = { version = "0.6.0", optional = true }
|
io-uring = { version = "0.6.1", optional = true }
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
remain = "0.2.11"
|
remain = "0.2.11"
|
||||||
smallvec = "1.10.0"
|
smallvec = "1.11.0"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
uuid = { version = "1.3.4", features = ["v4"] }
|
uuid = { version = "1.3.4", features = ["v4"] }
|
||||||
versionize = "0.1.10"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||||
virtio-queue = "0.8.0"
|
virtio-queue = "0.9.0"
|
||||||
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use libc::{ioctl, S_IFBLK, S_IFMT};
|
use crate::DiskTopology;
|
||||||
use std::fs::File;
|
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum DiskFileError {
|
pub enum DiskFileError {
|
||||||
@@ -19,88 +16,6 @@ pub enum DiskFileError {
|
|||||||
NewAsyncIo(#[source] std::io::Error),
|
NewAsyncIo(#[source] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct DiskTopology {
|
|
||||||
pub logical_block_size: u64,
|
|
||||||
pub physical_block_size: u64,
|
|
||||||
pub minimum_io_size: u64,
|
|
||||||
pub optimal_io_size: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DiskTopology {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
logical_block_size: 512,
|
|
||||||
physical_block_size: 512,
|
|
||||||
minimum_io_size: 512,
|
|
||||||
optimal_io_size: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ioctl_io_nr!(BLKSSZGET, 0x12, 104);
|
|
||||||
ioctl_io_nr!(BLKPBSZGET, 0x12, 123);
|
|
||||||
ioctl_io_nr!(BLKIOMIN, 0x12, 120);
|
|
||||||
ioctl_io_nr!(BLKIOOPT, 0x12, 121);
|
|
||||||
|
|
||||||
enum BlockSize {
|
|
||||||
LogicalBlock,
|
|
||||||
PhysicalBlock,
|
|
||||||
MinimumIo,
|
|
||||||
OptimalIo,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiskTopology {
|
|
||||||
fn is_block_device(f: &mut File) -> std::io::Result<bool> {
|
|
||||||
let mut stat = std::mem::MaybeUninit::<libc::stat>::uninit();
|
|
||||||
// SAFETY: FFI call with a valid fd and buffer
|
|
||||||
let ret = unsafe { libc::fstat(f.as_raw_fd(), stat.as_mut_ptr()) };
|
|
||||||
if ret != 0 {
|
|
||||||
return Err(std::io::Error::last_os_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: stat is valid at this point
|
|
||||||
let is_block = unsafe { (*stat.as_ptr()).st_mode & S_IFMT == S_IFBLK };
|
|
||||||
Ok(is_block)
|
|
||||||
}
|
|
||||||
|
|
||||||
// libc::ioctl() takes different types on different architectures
|
|
||||||
fn query_block_size(f: &mut File, block_size_type: BlockSize) -> std::io::Result<u64> {
|
|
||||||
let mut block_size = 0;
|
|
||||||
// SAFETY: FFI call with correct arguments
|
|
||||||
let ret = unsafe {
|
|
||||||
ioctl(
|
|
||||||
f.as_raw_fd(),
|
|
||||||
match block_size_type {
|
|
||||||
BlockSize::LogicalBlock => BLKSSZGET(),
|
|
||||||
BlockSize::PhysicalBlock => BLKPBSZGET(),
|
|
||||||
BlockSize::MinimumIo => BLKIOMIN(),
|
|
||||||
BlockSize::OptimalIo => BLKIOOPT(),
|
|
||||||
} as _,
|
|
||||||
&mut block_size,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if ret != 0 {
|
|
||||||
return Err(std::io::Error::last_os_error());
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(block_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn probe(f: &mut File) -> std::io::Result<Self> {
|
|
||||||
if !Self::is_block_device(f)? {
|
|
||||||
return Ok(DiskTopology::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(DiskTopology {
|
|
||||||
logical_block_size: Self::query_block_size(f, BlockSize::LogicalBlock)?,
|
|
||||||
physical_block_size: Self::query_block_size(f, BlockSize::PhysicalBlock)?,
|
|
||||||
minimum_io_size: Self::query_block_size(f, BlockSize::MinimumIo)?,
|
|
||||||
optimal_io_size: Self::query_block_size(f, BlockSize::OptimalIo)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
|
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
|
||||||
|
|
||||||
pub trait DiskFile: Send {
|
pub trait DiskFile: Send {
|
||||||
|
|||||||
150
block/src/lib.rs
150
block/src/lib.rs
@@ -35,6 +35,7 @@ use crate::qcow::{QcowFile, RawFile};
|
|||||||
use crate::vhdx::{Vhdx, VhdxError};
|
use crate::vhdx::{Vhdx, VhdxError};
|
||||||
#[cfg(feature = "io_uring")]
|
#[cfg(feature = "io_uring")]
|
||||||
use io_uring::{opcode, IoUring, Probe};
|
use io_uring::{opcode, IoUring, Probe};
|
||||||
|
use libc::{ioctl, S_IFBLK, S_IFMT};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@@ -44,6 +45,7 @@ use std::fmt::Debug;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||||
use std::os::linux::fs::MetadataExt;
|
use std::os::linux::fs::MetadataExt;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -60,6 +62,7 @@ use vm_memory::{
|
|||||||
};
|
};
|
||||||
use vm_virtio::{AccessPlatform, Translatable};
|
use vm_virtio::{AccessPlatform, Translatable};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
|
||||||
|
|
||||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||||
|
|
||||||
@@ -113,8 +116,8 @@ fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
|||||||
Ok(device_id)
|
Ok(device_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_disk_image_id(disk_path: &Path) -> Vec<u8> {
|
pub fn build_serial(disk_path: &Path) -> Vec<u8> {
|
||||||
let mut default_disk_image_id = vec![0; VIRTIO_BLK_ID_BYTES as usize];
|
let mut default_serial = vec![0; VIRTIO_BLK_ID_BYTES as usize];
|
||||||
match build_device_id(disk_path) {
|
match build_device_id(disk_path) {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Could not generate device id. We'll use a default.");
|
warn!("Could not generate device id. We'll use a default.");
|
||||||
@@ -124,17 +127,17 @@ pub fn build_disk_image_id(disk_path: &Path) -> Vec<u8> {
|
|||||||
// This will also zero out any leftover bytes.
|
// This will also zero out any leftover bytes.
|
||||||
let disk_id = m.as_bytes();
|
let disk_id = m.as_bytes();
|
||||||
let bytes_to_copy = cmp::min(disk_id.len(), VIRTIO_BLK_ID_BYTES as usize);
|
let bytes_to_copy = cmp::min(disk_id.len(), VIRTIO_BLK_ID_BYTES as usize);
|
||||||
default_disk_image_id[..bytes_to_copy].clone_from_slice(&disk_id[..bytes_to_copy])
|
default_serial[..bytes_to_copy].clone_from_slice(&disk_id[..bytes_to_copy])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default_disk_image_id
|
default_serial
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ExecuteError {
|
pub enum ExecuteError {
|
||||||
#[error("Bad request: {0}")]
|
#[error("Bad request: {0}")]
|
||||||
BadRequest(Error),
|
BadRequest(Error),
|
||||||
#[error("Falied to flush: {0}")]
|
#[error("Failed to flush: {0}")]
|
||||||
Flush(io::Error),
|
Flush(io::Error),
|
||||||
#[error("Failed to read: {0}")]
|
#[error("Failed to read: {0}")]
|
||||||
Read(GuestMemoryError),
|
Read(GuestMemoryError),
|
||||||
@@ -327,7 +330,7 @@ impl Request {
|
|||||||
disk: &mut T,
|
disk: &mut T,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
disk_id: &[u8],
|
serial: &[u8],
|
||||||
) -> result::Result<u32, ExecuteError> {
|
) -> result::Result<u32, ExecuteError> {
|
||||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||||
.map_err(ExecuteError::Seek)?;
|
.map_err(ExecuteError::Seek)?;
|
||||||
@@ -359,10 +362,10 @@ impl Request {
|
|||||||
}
|
}
|
||||||
RequestType::Flush => disk.flush().map_err(ExecuteError::Flush)?,
|
RequestType::Flush => disk.flush().map_err(ExecuteError::Flush)?,
|
||||||
RequestType::GetDeviceId => {
|
RequestType::GetDeviceId => {
|
||||||
if (*data_len as usize) < disk_id.len() {
|
if (*data_len as usize) < serial.len() {
|
||||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||||
}
|
}
|
||||||
mem.write_slice(disk_id, *data_addr)
|
mem.write_slice(serial, *data_addr)
|
||||||
.map_err(ExecuteError::Write)?;
|
.map_err(ExecuteError::Write)?;
|
||||||
}
|
}
|
||||||
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
||||||
@@ -376,7 +379,7 @@ impl Request {
|
|||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
disk_image: &mut dyn AsyncIo,
|
disk_image: &mut dyn AsyncIo,
|
||||||
disk_id: &[u8],
|
serial: &[u8],
|
||||||
user_data: u64,
|
user_data: u64,
|
||||||
) -> result::Result<bool, ExecuteError> {
|
) -> result::Result<bool, ExecuteError> {
|
||||||
let sector = self.sector;
|
let sector = self.sector;
|
||||||
@@ -403,13 +406,13 @@ impl Request {
|
|||||||
let origin_ptr = mem
|
let origin_ptr = mem
|
||||||
.get_slice(*data_addr, *data_len as usize)
|
.get_slice(*data_addr, *data_len as usize)
|
||||||
.map_err(ExecuteError::GetHostAddress)?
|
.map_err(ExecuteError::GetHostAddress)?
|
||||||
.as_ptr();
|
.ptr_guard();
|
||||||
|
|
||||||
// Verify the buffer alignment.
|
// Verify the buffer alignment.
|
||||||
// In case it's not properly aligned, an intermediate buffer is
|
// In case it's not properly aligned, an intermediate buffer is
|
||||||
// created with the correct alignment, and a copy from/to the
|
// created with the correct alignment, and a copy from/to the
|
||||||
// origin buffer is performed, depending on the type of operation.
|
// origin buffer is performed, depending on the type of operation.
|
||||||
let iov_base = if (origin_ptr as u64) % SECTOR_SIZE != 0 {
|
let iov_base = if (origin_ptr.as_ptr() as u64) % SECTOR_SIZE != 0 {
|
||||||
let layout =
|
let layout =
|
||||||
Layout::from_size_align(*data_len as usize, SECTOR_SIZE as usize).unwrap();
|
Layout::from_size_align(*data_len as usize, SECTOR_SIZE as usize).unwrap();
|
||||||
// SAFETY: layout has non-zero size
|
// SAFETY: layout has non-zero size
|
||||||
@@ -425,15 +428,13 @@ impl Request {
|
|||||||
if request_type == RequestType::Out {
|
if request_type == RequestType::Out {
|
||||||
// SAFETY: destination buffer has been allocated with
|
// SAFETY: destination buffer has been allocated with
|
||||||
// the proper size.
|
// the proper size.
|
||||||
unsafe {
|
unsafe { std::ptr::copy(origin_ptr.as_ptr(), aligned_ptr, *data_len as usize) };
|
||||||
std::ptr::copy(origin_ptr as *const u8, aligned_ptr, *data_len as usize)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store both origin and aligned pointers for complete_async()
|
// Store both origin and aligned pointers for complete_async()
|
||||||
// to process them.
|
// to process them.
|
||||||
self.aligned_operations.push(AlignedOperation {
|
self.aligned_operations.push(AlignedOperation {
|
||||||
origin_ptr: origin_ptr as u64,
|
origin_ptr: origin_ptr.as_ptr() as u64,
|
||||||
aligned_ptr: aligned_ptr as u64,
|
aligned_ptr: aligned_ptr as u64,
|
||||||
size: *data_len as usize,
|
size: *data_len as usize,
|
||||||
layout,
|
layout,
|
||||||
@@ -441,7 +442,7 @@ impl Request {
|
|||||||
|
|
||||||
aligned_ptr as *mut libc::c_void
|
aligned_ptr as *mut libc::c_void
|
||||||
} else {
|
} else {
|
||||||
origin_ptr as *mut libc::c_void
|
origin_ptr.as_ptr() as *mut libc::c_void
|
||||||
};
|
};
|
||||||
|
|
||||||
let iovec = libc::iovec {
|
let iovec = libc::iovec {
|
||||||
@@ -480,10 +481,10 @@ impl Request {
|
|||||||
} else {
|
} else {
|
||||||
return Err(ExecuteError::BadRequest(Error::TooManyDescriptors));
|
return Err(ExecuteError::BadRequest(Error::TooManyDescriptors));
|
||||||
};
|
};
|
||||||
if (data_len as usize) < disk_id.len() {
|
if (data_len as usize) < serial.len() {
|
||||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||||
}
|
}
|
||||||
mem.write_slice(disk_id, data_addr)
|
mem.write_slice(serial, data_addr)
|
||||||
.map_err(ExecuteError::Write)?;
|
.map_err(ExecuteError::Write)?;
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@@ -728,24 +729,33 @@ pub enum ImageType {
|
|||||||
const QCOW_MAGIC: u32 = 0x5146_49fb;
|
const QCOW_MAGIC: u32 = 0x5146_49fb;
|
||||||
const VHDX_SIGN: u64 = 0x656C_6966_7864_6876;
|
const VHDX_SIGN: u64 = 0x656C_6966_7864_6876;
|
||||||
|
|
||||||
|
/// Read a block into memory aligned by the source block size (needed for O_DIRECT)
|
||||||
|
pub fn read_aligned_block_size(f: &mut File) -> std::io::Result<Vec<u8>> {
|
||||||
|
let blocksize = DiskTopology::probe(f)?.logical_block_size as usize;
|
||||||
|
// SAFETY: We are allocating memory that is naturally aligned (size = alignment) and we meet
|
||||||
|
// requirements for safety from Vec::from_raw_parts() as we are using the global allocator
|
||||||
|
// and transferring ownership of the memory.
|
||||||
|
let mut data = unsafe {
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
alloc_zeroed(Layout::from_size_align_unchecked(blocksize, blocksize)),
|
||||||
|
blocksize,
|
||||||
|
blocksize,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
f.read_exact(&mut data)?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Determine image type through file parsing.
|
/// Determine image type through file parsing.
|
||||||
pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
|
pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
|
||||||
// We must create a buffer aligned on 512 bytes with a size being a
|
let block = read_aligned_block_size(f)?;
|
||||||
// multiple of 512 bytes as the file might be opened with O_DIRECT flag.
|
|
||||||
#[repr(align(512))]
|
|
||||||
struct Sector {
|
|
||||||
data: [u8; 512],
|
|
||||||
}
|
|
||||||
let mut s = Sector { data: [0; 512] };
|
|
||||||
|
|
||||||
f.read_exact(&mut s.data)?;
|
|
||||||
|
|
||||||
// Check 4 first bytes to get the header value and determine the image type
|
// Check 4 first bytes to get the header value and determine the image type
|
||||||
let image_type = if u32::from_be_bytes(s.data[0..4].try_into().unwrap()) == QCOW_MAGIC {
|
let image_type = if u32::from_be_bytes(block[0..4].try_into().unwrap()) == QCOW_MAGIC {
|
||||||
ImageType::Qcow2
|
ImageType::Qcow2
|
||||||
} else if vhd::is_fixed_vhd(f)? {
|
} else if vhd::is_fixed_vhd(f)? {
|
||||||
ImageType::FixedVhd
|
ImageType::FixedVhd
|
||||||
} else if u64::from_le_bytes(s.data[0..8].try_into().unwrap()) == VHDX_SIGN {
|
} else if u64::from_le_bytes(block[0..8].try_into().unwrap()) == VHDX_SIGN {
|
||||||
ImageType::Vhdx
|
ImageType::Vhdx
|
||||||
} else {
|
} else {
|
||||||
ImageType::Raw
|
ImageType::Raw
|
||||||
@@ -776,3 +786,85 @@ pub fn create_disk_file(mut file: File, direct_io: bool) -> Result<Box<dyn Block
|
|||||||
ImageType::Raw => Box::new(RawFile::new(file, direct_io)) as Box<dyn BlockBackend>,
|
ImageType::Raw => Box::new(RawFile::new(file, direct_io)) as Box<dyn BlockBackend>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DiskTopology {
|
||||||
|
pub logical_block_size: u64,
|
||||||
|
pub physical_block_size: u64,
|
||||||
|
pub minimum_io_size: u64,
|
||||||
|
pub optimal_io_size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DiskTopology {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
logical_block_size: 512,
|
||||||
|
physical_block_size: 512,
|
||||||
|
minimum_io_size: 512,
|
||||||
|
optimal_io_size: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl_io_nr!(BLKSSZGET, 0x12, 104);
|
||||||
|
ioctl_io_nr!(BLKPBSZGET, 0x12, 123);
|
||||||
|
ioctl_io_nr!(BLKIOMIN, 0x12, 120);
|
||||||
|
ioctl_io_nr!(BLKIOOPT, 0x12, 121);
|
||||||
|
|
||||||
|
enum BlockSize {
|
||||||
|
LogicalBlock,
|
||||||
|
PhysicalBlock,
|
||||||
|
MinimumIo,
|
||||||
|
OptimalIo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DiskTopology {
|
||||||
|
fn is_block_device(f: &File) -> std::io::Result<bool> {
|
||||||
|
let mut stat = std::mem::MaybeUninit::<libc::stat>::uninit();
|
||||||
|
// SAFETY: FFI call with a valid fd and buffer
|
||||||
|
let ret = unsafe { libc::fstat(f.as_raw_fd(), stat.as_mut_ptr()) };
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: stat is valid at this point
|
||||||
|
let is_block = unsafe { (*stat.as_ptr()).st_mode & S_IFMT == S_IFBLK };
|
||||||
|
Ok(is_block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// libc::ioctl() takes different types on different architectures
|
||||||
|
fn query_block_size(f: &File, block_size_type: BlockSize) -> std::io::Result<u64> {
|
||||||
|
let mut block_size = 0;
|
||||||
|
// SAFETY: FFI call with correct arguments
|
||||||
|
let ret = unsafe {
|
||||||
|
ioctl(
|
||||||
|
f.as_raw_fd(),
|
||||||
|
match block_size_type {
|
||||||
|
BlockSize::LogicalBlock => BLKSSZGET(),
|
||||||
|
BlockSize::PhysicalBlock => BLKPBSZGET(),
|
||||||
|
BlockSize::MinimumIo => BLKIOMIN(),
|
||||||
|
BlockSize::OptimalIo => BLKIOOPT(),
|
||||||
|
} as _,
|
||||||
|
&mut block_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(block_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn probe(f: &File) -> std::io::Result<Self> {
|
||||||
|
if !Self::is_block_device(f)? {
|
||||||
|
return Ok(DiskTopology::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(DiskTopology {
|
||||||
|
logical_block_size: Self::query_block_size(f, BlockSize::LogicalBlock)?,
|
||||||
|
physical_block_size: Self::query_block_size(f, BlockSize::PhysicalBlock)?,
|
||||||
|
minimum_io_size: Self::query_block_size(f, BlockSize::MinimumIo)?,
|
||||||
|
optimal_io_size: Self::query_block_size(f, BlockSize::OptimalIo)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, DiskTopology,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||||
};
|
};
|
||||||
|
use crate::DiskTopology;
|
||||||
use io_uring::{opcode, squeue, types, IoUring};
|
use io_uring::{opcode, squeue, types, IoUring};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
@@ -36,7 +37,7 @@ impl DiskFile for RawFileDisk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn topology(&mut self) -> DiskTopology {
|
fn topology(&mut self) -> DiskTopology {
|
||||||
if let Ok(topology) = DiskTopology::probe(&mut self.file) {
|
if let Ok(topology) = DiskTopology::probe(&self.file) {
|
||||||
topology
|
topology
|
||||||
} else {
|
} else {
|
||||||
warn!("Unable to get device topology. Using default topology");
|
warn!("Unable to get device topology. Using default topology");
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, DiskTopology,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||||
};
|
};
|
||||||
|
use crate::DiskTopology;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
@@ -33,7 +34,7 @@ impl DiskFile for RawFileDiskSync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn topology(&mut self) -> DiskTopology {
|
fn topology(&mut self) -> DiskTopology {
|
||||||
if let Ok(topology) = DiskTopology::probe(&mut self.file) {
|
if let Ok(topology) = DiskTopology::probe(&self.file) {
|
||||||
topology
|
topology
|
||||||
} else {
|
} else {
|
||||||
warn!("Unable to get device topology. Using default topology");
|
warn!("Unable to get device topology. Using default topology");
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::{read_aligned_block_size, DiskTopology};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct VhdFooter {
|
pub struct VhdFooter {
|
||||||
@@ -27,37 +28,33 @@ pub struct VhdFooter {
|
|||||||
|
|
||||||
impl VhdFooter {
|
impl VhdFooter {
|
||||||
pub fn new(file: &mut File) -> std::io::Result<VhdFooter> {
|
pub fn new(file: &mut File) -> std::io::Result<VhdFooter> {
|
||||||
// We must create a buffer aligned on 512 bytes with a size being a
|
let blocksize = DiskTopology::probe(file)?.logical_block_size as usize;
|
||||||
// multiple of 512 bytes as the file might be opened with O_DIRECT flag.
|
|
||||||
#[repr(align(512))]
|
|
||||||
struct Sector {
|
|
||||||
data: [u8; 512],
|
|
||||||
}
|
|
||||||
let mut s = Sector { data: [0; 512] };
|
|
||||||
|
|
||||||
// Place the cursor 512 bytes before the end of the file, as this is
|
// Place the cursor in the last block of the file
|
||||||
// where the footer starts.
|
file.seek(SeekFrom::End(0 - (blocksize as i64)))?;
|
||||||
file.seek(SeekFrom::End(-512))?;
|
// Read in the last block
|
||||||
|
let data = read_aligned_block_size(file)?;
|
||||||
|
|
||||||
// Fill in the VhdFooter structure
|
// We only care about the last sector
|
||||||
file.read_exact(&mut s.data)?;
|
let offset = blocksize - 512;
|
||||||
|
let sector = &data[offset..];
|
||||||
|
|
||||||
Ok(VhdFooter {
|
Ok(VhdFooter {
|
||||||
cookie: u64::from_be_bytes(s.data[0..8].try_into().unwrap()),
|
cookie: u64::from_be_bytes(sector[0..8].try_into().unwrap()),
|
||||||
features: u32::from_be_bytes(s.data[8..12].try_into().unwrap()),
|
features: u32::from_be_bytes(sector[8..12].try_into().unwrap()),
|
||||||
file_format_version: u32::from_be_bytes(s.data[12..16].try_into().unwrap()),
|
file_format_version: u32::from_be_bytes(sector[12..16].try_into().unwrap()),
|
||||||
data_offset: u64::from_be_bytes(s.data[16..24].try_into().unwrap()),
|
data_offset: u64::from_be_bytes(sector[16..24].try_into().unwrap()),
|
||||||
time_stamp: u32::from_be_bytes(s.data[24..28].try_into().unwrap()),
|
time_stamp: u32::from_be_bytes(sector[24..28].try_into().unwrap()),
|
||||||
creator_application: u32::from_be_bytes(s.data[28..32].try_into().unwrap()),
|
creator_application: u32::from_be_bytes(sector[28..32].try_into().unwrap()),
|
||||||
creator_version: u32::from_be_bytes(s.data[32..36].try_into().unwrap()),
|
creator_version: u32::from_be_bytes(sector[32..36].try_into().unwrap()),
|
||||||
creator_host_os: u32::from_be_bytes(s.data[36..40].try_into().unwrap()),
|
creator_host_os: u32::from_be_bytes(sector[36..40].try_into().unwrap()),
|
||||||
original_size: u64::from_be_bytes(s.data[40..48].try_into().unwrap()),
|
original_size: u64::from_be_bytes(sector[40..48].try_into().unwrap()),
|
||||||
current_size: u64::from_be_bytes(s.data[48..56].try_into().unwrap()),
|
current_size: u64::from_be_bytes(sector[48..56].try_into().unwrap()),
|
||||||
disk_geometry: u32::from_be_bytes(s.data[56..60].try_into().unwrap()),
|
disk_geometry: u32::from_be_bytes(sector[56..60].try_into().unwrap()),
|
||||||
disk_type: u32::from_be_bytes(s.data[60..64].try_into().unwrap()),
|
disk_type: u32::from_be_bytes(sector[60..64].try_into().unwrap()),
|
||||||
checksum: u32::from_be_bytes(s.data[64..68].try_into().unwrap()),
|
checksum: u32::from_be_bytes(sector[64..68].try_into().unwrap()),
|
||||||
unique_id: u128::from_be_bytes(s.data[68..84].try_into().unwrap()),
|
unique_id: u128::from_be_bytes(sector[68..84].try_into().unwrap()),
|
||||||
saved_state: u8::from_be_bytes(s.data[84..85].try_into().unwrap()),
|
saved_state: u8::from_be_bytes(sector[84..85].try_into().unwrap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ pub enum VhdxHeaderError {
|
|||||||
SeekRegionTableEntries(#[source] io::Error),
|
SeekRegionTableEntries(#[source] io::Error),
|
||||||
#[error("Failed to seek in region table header {0}")]
|
#[error("Failed to seek in region table header {0}")]
|
||||||
SeekRegionTableHeader(#[source] io::Error),
|
SeekRegionTableHeader(#[source] io::Error),
|
||||||
#[error("We do not recongize this entry")]
|
#[error("We do not recognize this entry")]
|
||||||
UnrecognizedRegionEntry,
|
UnrecognizedRegionEntry,
|
||||||
#[error("Failed to write header {0}")]
|
#[error("Failed to write header {0}")]
|
||||||
WriteHeader(#[source] io::Error),
|
WriteHeader(#[source] io::Error),
|
||||||
@@ -305,7 +305,7 @@ impl RegionInfo {
|
|||||||
|
|
||||||
if (entry.required & REGION_ENTRY_REQUIRED) == 1 {
|
if (entry.required & REGION_ENTRY_REQUIRED) == 1 {
|
||||||
// This implementation doesn't recognize this field.
|
// This implementation doesn't recognize this field.
|
||||||
// Therefore, accoding to the spec, we are throwing an error.
|
// Therefore, according to the spec, we are throwing an error.
|
||||||
return Err(VhdxHeaderError::UnrecognizedRegionEntry);
|
return Err(VhdxHeaderError::UnrecognizedRegionEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,7 +444,7 @@ impl VhdxHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the provided headers accoding to the spec
|
// Update the provided headers according to the spec
|
||||||
fn update_headers(
|
fn update_headers(
|
||||||
f: &mut File,
|
f: &mut File,
|
||||||
header_1: Result<Header>,
|
header_1: Result<Header>,
|
||||||
@@ -468,7 +468,7 @@ impl VhdxHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the checksum of a buffer that itself containts its checksum
|
/// Calculates the checksum of a buffer that itself contains its checksum
|
||||||
/// Therefore, before calculating, the existing checksum is retrieved and the
|
/// Therefore, before calculating, the existing checksum is retrieved and the
|
||||||
/// corresponding field is made zero. After the calculation, the existing checksum
|
/// corresponding field is made zero. After the calculation, the existing checksum
|
||||||
/// is put back to the buffer.
|
/// is put back to the buffer.
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ pub struct DiskSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DiskSpec {
|
impl DiskSpec {
|
||||||
/// Parse all meatadata from the provided file and store info in DiskSpec
|
/// Parse all metadata from the provided file and store info in DiskSpec
|
||||||
/// structure.
|
/// structure.
|
||||||
pub fn new(f: &mut File, metadata_region: &RegionTableEntry) -> Result<DiskSpec> {
|
pub fn new(f: &mut File, metadata_region: &RegionTableEntry) -> Result<DiskSpec> {
|
||||||
let mut disk_spec = DiskSpec::default();
|
let mut disk_spec = DiskSpec::default();
|
||||||
@@ -133,7 +133,7 @@ impl DiskSpec {
|
|||||||
.map_err(VhdxMetadataError::ReadMetadata)?;
|
.map_err(VhdxMetadataError::ReadMetadata)?;
|
||||||
|
|
||||||
// MUST be at least 1 MiB and not greater than 256 MiB
|
// MUST be at least 1 MiB and not greater than 256 MiB
|
||||||
if disk_spec.block_size < BLOCK_SIZE_MIN && disk_spec.block_size > BLOCK_SIZE_MAX {
|
if disk_spec.block_size < BLOCK_SIZE_MIN || disk_spec.block_size > BLOCK_SIZE_MAX {
|
||||||
return Err(VhdxMetadataError::InvalidBlockSize);
|
return Err(VhdxMetadataError::InvalidBlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
bitflags = "2.3.3"
|
bitflags = "2.3.3"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
event_monitor = { path = "../event_monitor" }
|
event_monitor = { path = "../event_monitor" }
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
pci = { path = "../pci" }
|
pci = { path = "../pci" }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
@@ -21,7 +21,7 @@ versionize = "0.1.10"
|
|||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ impl Aml for AcpiGedDevice {
|
|||||||
&aml::Name::new(
|
&aml::Name::new(
|
||||||
"_CRS".into(),
|
"_CRS".into(),
|
||||||
&aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory(
|
&aml::ResourceTemplate::new(vec![&aml::AddressSpace::new_memory(
|
||||||
aml::AddressSpaceCachable::NotCacheable,
|
aml::AddressSpaceCacheable::NotCacheable,
|
||||||
true,
|
true,
|
||||||
self.address.0,
|
self.address.0,
|
||||||
self.address.0 + GED_DEVICE_ACPI_SIZE as u64 - 1,
|
self.address.0 + GED_DEVICE_ACPI_SIZE as u64 - 1,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub const IRQ_LEGACY_BASE: usize = layout::IRQ_BASE as usize;
|
|||||||
pub const IRQ_LEGACY_COUNT: usize = 32;
|
pub const IRQ_LEGACY_COUNT: usize = 32;
|
||||||
pub const GIC_SNAPSHOT_ID: &str = "gic-v3-its";
|
pub const GIC_SNAPSHOT_ID: &str = "gic-v3-its";
|
||||||
|
|
||||||
// Gic (Generic Interupt Controller) struct provides all the functionality of a
|
// Gic (Generic Interrupt Controller) struct provides all the functionality of a
|
||||||
// GIC device. It wraps a hypervisor-emulated GIC device (Vgic) provided by the
|
// GIC device. It wraps a hypervisor-emulated GIC device (Vgic) provided by the
|
||||||
// `hypervisor` crate.
|
// `hypervisor` crate.
|
||||||
// Gic struct also implements InterruptController to provide interrupt delivery
|
// Gic struct also implements InterruptController to provide interrupt delivery
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const GPIOIC: u64 = 0x41c; // Interrupt Clear Register
|
|||||||
const GPIOAFSEL: u64 = 0x420; // Mode Control Select Register
|
const GPIOAFSEL: u64 = 0x420; // Mode Control Select Register
|
||||||
// From 0x424 to 0xFDC => reserved space.
|
// From 0x424 to 0xFDC => reserved space.
|
||||||
// From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers.
|
// From 0xFE0 to 0xFFC => Peripheral and PrimeCell Identification Registers which are Read Only registers.
|
||||||
// Thses registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral.
|
// These registers can conceptually be treated as a 32-bit register, and PartNumber[11:0] is used to identify the peripheral.
|
||||||
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
|
// We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
|
||||||
const GPIO_ID: [u8; 8] = [0x61, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
|
const GPIO_ID: [u8; 8] = [0x61, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
|
||||||
// ID Margins
|
// ID Margins
|
||||||
@@ -57,7 +57,7 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "Could not trigger GPIO interrupt: {e}.")
|
write!(f, "Could not trigger GPIO interrupt: {e}.")
|
||||||
}
|
}
|
||||||
Error::GpioTriggerKeyFailure(key) => {
|
Error::GpioTriggerKeyFailure(key) => {
|
||||||
write!(f, "Invalid GPIO Input key triggerd: {key}.")
|
write!(f, "Invalid GPIO Input key triggered: {key}.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const PVPANIC_VENDOR_ID: u16 = 0x1b36;
|
|||||||
const PVPANIC_DEVICE_ID: u16 = 0x0011;
|
const PVPANIC_DEVICE_ID: u16 = 0x0011;
|
||||||
|
|
||||||
pub const PVPANIC_DEVICE_MMIO_SIZE: u64 = 0x2;
|
pub const PVPANIC_DEVICE_MMIO_SIZE: u64 = 0x2;
|
||||||
|
pub const PVPANIC_DEVICE_MMIO_ALIGNMENT: u64 = 0x10;
|
||||||
|
|
||||||
const PVPANIC_PANICKED: u8 = 1 << 0;
|
const PVPANIC_PANICKED: u8 = 1 << 0;
|
||||||
const PVPANIC_CRASH_LOADED: u8 = 1 << 1;
|
const PVPANIC_CRASH_LOADED: u8 = 1 << 1;
|
||||||
@@ -38,9 +39,8 @@ pub enum PvPanicError {
|
|||||||
RetrievePciConfigurationState(#[source] anyhow::Error),
|
RetrievePciConfigurationState(#[source] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum PvPanicSubclass {
|
enum PvPanicSubclass {
|
||||||
Other = 0x80,
|
Other = 0x80,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ impl PciDevice for PvPanicDevice {
|
|||||||
let bar_addr = allocator
|
let bar_addr = allocator
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.allocate_mmio_hole_addresses(None, region_size, None)
|
.allocate_mmio_hole_addresses(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
|
||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
||||||
|
|
||||||
let bar = PciBarConfiguration::default()
|
let bar = PciBarConfiguration::default()
|
||||||
|
|||||||
38
docs/amd_sev_snp.md
Normal file
38
docs/amd_sev_snp.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# AMD SEV-SNP
|
||||||
|
|
||||||
|
### WARNING
|
||||||
|
This feature is only currently supported on MSHV.
|
||||||
|
|
||||||
|
AMD Secure Encrypted Virtualization & Secure Nested Paging (SEV-SNP) is an AMD
|
||||||
|
technology designed to add strong memory integrity protection to help prevent
|
||||||
|
malicious hypervisor-based attacks like data replay, memory-remapping and more
|
||||||
|
in order to create an isolated execution environment. Here are some useful
|
||||||
|
links:
|
||||||
|
|
||||||
|
* [SNP Homepage] (https://www.amd.com/en/processors/amd-secure-encrypted-virtualization)
|
||||||
|
more information about SEV-SNP technical aspects, design and specification.
|
||||||
|
|
||||||
|
## Cloud Hypervisor support
|
||||||
|
|
||||||
|
It is required to use a machine which has enabled support for AMD SEV-SNP in
|
||||||
|
the BIOS.
|
||||||
|
|
||||||
|
On the Cloud Hypervisor side, all you need is to build the project with the
|
||||||
|
`sev_snp` feature enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --no-default-features --features "sev_snp"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**
|
||||||
|
Please note that `sev_snp` cannot be enabled in conjunction with `tdx` feature flag.
|
||||||
|
|
||||||
|
You can run a SEV-SNP VM using the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./cloud-hypervisor \
|
||||||
|
--platform sev_snp=on \
|
||||||
|
--cpus boot=1 \
|
||||||
|
--memory size=1G \
|
||||||
|
--disk path=ubuntu.img
|
||||||
|
```
|
||||||
32
docs/api.md
32
docs/api.md
@@ -206,11 +206,14 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1
|
|||||||
|
|
||||||
### D-Bus API
|
### D-Bus API
|
||||||
|
|
||||||
Cloud Hypervisor offers a D-Bus API as an alternative to its REST API. As of
|
Cloud Hypervisor offers a D-Bus API as an alternative to its REST API. This
|
||||||
writing this document, the D-Bus API mirrors the functionality of the REST
|
D-Bus API fully reflects the functionality of the REST API, exposing the
|
||||||
API and shares the same set of endpoints, meaning that it supports every call
|
same group of endpoints. It can be a drop-in replacement since it also
|
||||||
that is supported by the REST API and can be a drop-in replacement since it
|
consumes/produces JSON.
|
||||||
also consumes/produces JSON.
|
|
||||||
|
In addition, the D-Bus API also exposes events from `event-monitor` in the
|
||||||
|
form of a D-Bus signal to which users can subscribe. For more information,
|
||||||
|
see [D-Bus API Interface](#d-bus-api-interface).
|
||||||
|
|
||||||
#### D-Bus API Location and availability
|
#### D-Bus API Location and availability
|
||||||
|
|
||||||
@@ -245,8 +248,23 @@ which in turn can be used to control and manage Cloud Hypervisor.
|
|||||||
|
|
||||||
#### D-Bus API Interface
|
#### D-Bus API Interface
|
||||||
|
|
||||||
Please refer to the [REST API](#rest-api) documentation. As previously
|
Please refer to the [REST API](#rest-api) documentation for everything that
|
||||||
mentioned, the D-Bus API currently mirrors the behaviour of the REST API.
|
is in common with the REST API. As previously mentioned, the D-Bus API can
|
||||||
|
be used as a drop-in replacement for the [REST API](#rest-api).
|
||||||
|
|
||||||
|
The D-Bus interface also exposes a signal, named `Event`, which is emitted
|
||||||
|
whenever a new event is published from the `event-monitor` crate. Here is its
|
||||||
|
definition in XML format:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<node>
|
||||||
|
<interface name="org.cloudhypervisor.DBusApi1">
|
||||||
|
<signal name="Event">
|
||||||
|
<arg name="event" type="s"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>
|
||||||
|
```
|
||||||
|
|
||||||
### Command Line Interface
|
### Command Line Interface
|
||||||
|
|
||||||
|
|||||||
@@ -47,12 +47,15 @@ The custom Linux kernel for the guest can be built with the [TDX Tools](https://
|
|||||||
The firmware can be built as follows:
|
The firmware can be built as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install uuid-dev nasm iasl build-essential python3-distutils git
|
||||||
|
|
||||||
git clone https://github.com/tianocore/edk2.git
|
git clone https://github.com/tianocore/edk2.git
|
||||||
cd edk2
|
cd edk2
|
||||||
git checkout 13b97736c876919b9786055829caaa4fa46984b7
|
git checkout 13b97736c876919b9786055829caaa4fa46984b7
|
||||||
git submodule update --init --recursive
|
|
||||||
make -C BaseTools
|
|
||||||
source ./edksetup.sh
|
source ./edksetup.sh
|
||||||
|
git submodule update --init --recursive
|
||||||
|
make -C BaseTools -j `nproc`
|
||||||
build -p OvmfPkg/IntelTdx/IntelTdxX64.dsc -a X64 -t GCC5 -b RELEASE
|
build -p OvmfPkg/IntelTdx/IntelTdxX64.dsc -a X64 -t GCC5 -b RELEASE
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ The target audience of this document is both:
|
|||||||
|
|
||||||
## Control
|
## Control
|
||||||
|
|
||||||
The number of `-v` parameters passed to the `cloud-hypervisor` binary will determine the log level. Currenly the default is log messages up to `WARN:` (`warn!`) are included by default. The `--log-file` allows the log to be sent to a location other than `stderr`.
|
The number of `-v` parameters passed to the `cloud-hypervisor` binary will determine the log level. Currently the default is log messages up to `WARN:` (`warn!`) are included by default. The `--log-file` allows the log to be sent to a location other than `stderr`.
|
||||||
|
|
||||||
## Levels
|
## Levels
|
||||||
|
|
||||||
### `error!()`
|
### `error!()`
|
||||||
|
|
||||||
For immediate, unrecoverable errors where it does not make sense for the execution to continue as the behaviour of the VM is considerablely impacted.
|
For immediate, unrecoverable errors where it does not make sense for the execution to continue as the behaviour of the VM is considerably impacted.
|
||||||
|
|
||||||
Cloud Hypervisor should exit shortly after reporting this error (with a non-zero exit code). Generally this should be used during initial construction of the VM state before the virtual CPUs have begun running code.
|
Cloud Hypervisor should exit shortly after reporting this error (with a non-zero exit code). Generally this should be used during initial construction of the VM state before the virtual CPUs have begun running code.
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ Users should react to this error by checking their initial VM configuration.
|
|||||||
|
|
||||||
### `warn!()`
|
### `warn!()`
|
||||||
|
|
||||||
A serious problem has occured but the execution of the VM can continue although some functionality might be impacted.
|
A serious problem has occurred but the execution of the VM can continue although some functionality might be impacted.
|
||||||
|
|
||||||
A typical example of where this level of message should be generated is during an API call request that cannot be fulfilled.
|
A typical example of where this level of message should be generated is during an API call request that cannot be fulfilled.
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ struct MemoryZoneConfig {
|
|||||||
--memory-zone <memory-zone> User defined memory zone parameters "size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,hugepage_size=<hugepage_size>,host_numa_node=<node_id>,id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,prefault=on|off"
|
--memory-zone <memory-zone> User defined memory zone parameters "size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,hugepage_size=<hugepage_size>,host_numa_node=<node_id>,id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,prefault=on|off"
|
||||||
```
|
```
|
||||||
|
|
||||||
This parameter expects one or more occurences, allowing for a list of memory
|
This parameter expects one or more occurrences, allowing for a list of memory
|
||||||
zones to be defined. It must be used with `--memory size=0`, clearly indicating
|
zones to be defined. It must be used with `--memory size=0`, clearly indicating
|
||||||
that the memory will be described through advanced parameters.
|
that the memory will be described through advanced parameters.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Tracing
|
# Tracing
|
||||||
|
|
||||||
Cloud Hypervisor has a basic tracing infrastucture, particularly focussed on
|
Cloud Hypervisor has a basic tracing infrastructure, particularly focussed on
|
||||||
the tracing of the initial VM setup.
|
the tracing of the initial VM setup.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ This section illustrates the Windows specific aspects of the VM network configur
|
|||||||
|
|
||||||
### Basic Networking
|
### Basic Networking
|
||||||
|
|
||||||
As the simplest option, using `--net tap=` in the Cloud Hypervisor command line will create a `vmtapX` device on the host with the default IPv4 adress `192.168.249.1`. After SAC becomes available, the guest configuration can be set with
|
As the simplest option, using `--net tap=` in the Cloud Hypervisor command line will create a `vmtapX` device on the host with the default IPv4 address `192.168.249.1`. After SAC becomes available, the guest configuration can be set with
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
SAC>i 10 192.168.249.2 255.255.255.0 192.168.249.1
|
SAC>i 10 192.168.249.2 255.255.255.0 192.168.249.1
|
||||||
@@ -203,13 +203,13 @@ The Windows guest debugging process relies heavily on QEMU and [socat](http://ww
|
|||||||
|
|
||||||
The connection between both guests happens over TCP, whereby on the guest side it is automatically translated to a COM port. Because the VMs are connected through TCP, the debugging infrastructure can be distributed over the network. The serial port, while slowly transferring data, is common enough to support a wide range of cases and tools.
|
The connection between both guests happens over TCP, whereby on the guest side it is automatically translated to a COM port. Because the VMs are connected through TCP, the debugging infrastructure can be distributed over the network. The serial port, while slowly transferring data, is common enough to support a wide range of cases and tools.
|
||||||
|
|
||||||
In this excercise, [WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) is used. Any other debugger of choice with the ability to use serial connection can be used instead.
|
In this exercise, [WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) is used. Any other debugger of choice with the ability to use serial connection can be used instead.
|
||||||
|
|
||||||
### Debugger and Debuggee
|
### Debugger and Debuggee
|
||||||
|
|
||||||
#### WinDbg VM
|
#### WinDbg VM
|
||||||
|
|
||||||
For simplicity, the debugger VM is supposed to be only running under QEMU. It will require VGA and doesn't neccessarily depend on UEFI. As an OS, it can carry any supported Windows OS where the debugger of choice can be installed. The simplest way is to follow the image preparation instructions from the previous chapter, but avoid using the OVMF firmware. It is also not required to use VirtIO drivers, whereby it might be useful in some case. Though, while creating the image file for the debugger VM, be sure to choose a sufficient disk size that counts in the need to save the corresponding debug symbols and sources.
|
For simplicity, the debugger VM is supposed to be only running under QEMU. It will require VGA and doesn't necessarily depend on UEFI. As an OS, it can carry any supported Windows OS where the debugger of choice can be installed. The simplest way is to follow the image preparation instructions from the previous chapter, but avoid using the OVMF firmware. It is also not required to use VirtIO drivers, whereby it might be useful in some case. Though, while creating the image file for the debugger VM, be sure to choose a sufficient disk size that counts in the need to save the corresponding debug symbols and sources.
|
||||||
|
|
||||||
To create the debugger Windows VM, the following command can be used:
|
To create the debugger Windows VM, the following command can be used:
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ This will configure the debugging to be enabled and instruct to use the serial p
|
|||||||
bcdedit /dbgsettings serial debugport:1 baudrate:115200
|
bcdedit /dbgsettings serial debugport:1 baudrate:115200
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Turn On Kernel Debuging
|
##### Turn On Kernel Debugging
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
bcdedit /debug on
|
bcdedit /debug on
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flume = "0.10.14"
|
flume = "0.10.14"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
once_cell = "1.18.0"
|
||||||
serde_json = "1.0.96"
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
|
serde_json = "1.0.107"
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
static mut MONITOR: Option<MonitorHandle> = None;
|
static MONITOR: OnceCell<MonitorHandle> = OnceCell::new();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Event<'a> {
|
struct Event<'a> {
|
||||||
@@ -23,7 +25,24 @@ struct Event<'a> {
|
|||||||
|
|
||||||
pub struct Monitor {
|
pub struct Monitor {
|
||||||
pub rx: flume::Receiver<String>,
|
pub rx: flume::Receiver<String>,
|
||||||
pub file: File,
|
pub file: Option<File>,
|
||||||
|
pub broadcast: Vec<flume::Sender<Arc<String>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Monitor {
|
||||||
|
pub fn new(rx: flume::Receiver<String>, file: Option<File>) -> Self {
|
||||||
|
Self {
|
||||||
|
rx,
|
||||||
|
file,
|
||||||
|
broadcast: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe(&mut self) -> flume::Receiver<Arc<String>> {
|
||||||
|
let (tx, rx) = flume::unbounded();
|
||||||
|
self.broadcast.push(tx);
|
||||||
|
rx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MonitorHandle {
|
struct MonitorHandle {
|
||||||
@@ -50,32 +69,32 @@ fn set_file_nonblocking(file: &File) -> io::Result<()> {
|
|||||||
|
|
||||||
/// This function must only be called once from the main thread before any threads
|
/// This function must only be called once from the main thread before any threads
|
||||||
/// are created to avoid race conditions.
|
/// are created to avoid race conditions.
|
||||||
pub fn set_monitor(file: File) -> io::Result<Monitor> {
|
pub fn set_monitor(file: Option<File>) -> io::Result<Monitor> {
|
||||||
// SAFETY: there is only one caller of this function, so MONITOR is written to only once
|
// There is only one caller of this function, so MONITOR is written to only once
|
||||||
assert!(unsafe { MONITOR.is_none() });
|
assert!(MONITOR.get().is_none());
|
||||||
|
|
||||||
|
if let Some(ref file) = file {
|
||||||
|
set_file_nonblocking(file)?;
|
||||||
|
}
|
||||||
|
|
||||||
set_file_nonblocking(&file)?;
|
|
||||||
let (tx, rx) = flume::unbounded();
|
let (tx, rx) = flume::unbounded();
|
||||||
let monitor = Monitor { rx, file };
|
let monitor = Monitor::new(rx, file);
|
||||||
|
|
||||||
// SAFETY: MONITOR is None. Nobody else can hold a reference to it.
|
MONITOR.get_or_init(|| MonitorHandle {
|
||||||
unsafe {
|
tx,
|
||||||
MONITOR = Some(MonitorHandle {
|
start: Instant::now(),
|
||||||
tx,
|
});
|
||||||
start: Instant::now(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(monitor)
|
Ok(monitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>, Cow<str>>>) {
|
pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>, Cow<str>>>) {
|
||||||
// SAFETY: `MONITOR` is always in a valid state (None or Some), because it
|
// `MONITOR` is always in a valid state (None or Some), because it is set
|
||||||
// is set only once before any threads are spawned, and it's not mutated
|
// only once before any threads are spawned, and it's not mutated
|
||||||
// afterwards. This function only creates immutable references to `MONITOR`.
|
// afterwards. This function only creates immutable references to `MONITOR`.
|
||||||
// Because `MONITOR.tx` is `Sync`, it's safe to share `MONITOR` across
|
// Because `MONITOR.tx` is `Sync`, it's safe to share `MONITOR` across
|
||||||
// threads, making this function thread-safe.
|
// threads, making this function thread-safe.
|
||||||
if let Some(monitor_handle) = unsafe { MONITOR.as_ref() } {
|
if let Some(monitor_handle) = MONITOR.get().as_ref() {
|
||||||
let event = Event {
|
let event = Event {
|
||||||
timestamp: monitor_handle.start.elapsed(),
|
timestamp: monitor_handle.start.elapsed(),
|
||||||
source,
|
source,
|
||||||
|
|||||||
117
fuzz/Cargo.lock
generated
117
fuzz/Cargo.lock
generated
@@ -5,16 +5,16 @@ version = 3
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "acpi_tables"
|
name = "acpi_tables"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#05a609136387cc1cc9b499cee4320020325c263f"
|
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#1029d22777f07b04849234bbe756da34a6df2913"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.72"
|
version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -59,9 +59,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argh"
|
name = "argh"
|
||||||
version = "0.1.10"
|
version = "0.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e"
|
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argh_derive",
|
"argh_derive",
|
||||||
"argh_shared",
|
"argh_shared",
|
||||||
@@ -69,21 +69,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argh_derive"
|
name = "argh_derive"
|
||||||
version = "0.1.10"
|
version = "0.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6"
|
checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argh_shared",
|
"argh_shared",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argh_shared"
|
name = "argh_shared"
|
||||||
version = "0.1.10"
|
version = "0.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
|
checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
@@ -148,9 +151,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -164,7 +167,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "33.0.0"
|
version = "34.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -301,6 +304,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"flume",
|
"flume",
|
||||||
"libc",
|
"libc",
|
||||||
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@@ -381,9 +385,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-uring"
|
name = "io-uring"
|
||||||
version = "0.6.0"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b7b36074613a723279637061b40db993208908a94f10ccb14436ce735bc0f57"
|
checksum = "460648e47a07a43110fbfa2e0b14afb2be920093c31e5dccc50e49568e099762"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -436,15 +440,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.148"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
version = "0.4.6"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
|
checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -453,9 +457,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-loader"
|
name = "linux-loader"
|
||||||
version = "0.9.0"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d3adb7b28e189741eca3b1a4a27de0bf15e0907c9d4b0c74bd2d7d84ef72e08"
|
checksum = "1db6a725c8000971f83fa93ed7ee1b600e55a1471a2a653379d3c84f72effdcf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
@@ -472,14 +476,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.19"
|
version = "0.4.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#b538bf89e50be83b6fa9ab1896727ff61e02fa13"
|
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#0d0fdcd50ea10c1b4777f9a958873fc848a5b7bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -586,9 +590,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.32"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -671,9 +675,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.104"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -682,9 +686,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with"
|
name = "serde_with"
|
||||||
version = "3.2.0"
|
version = "3.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49"
|
checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_with_macros",
|
"serde_with_macros",
|
||||||
@@ -692,9 +696,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with_macros"
|
name = "serde_with_macros"
|
||||||
version = "3.2.0"
|
version = "3.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7"
|
checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -727,9 +731,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.11.0"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
@@ -770,18 +774,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.44"
|
version = "1.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.44"
|
version = "1.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -814,9 +818,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.11"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
@@ -857,7 +861,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -865,7 +869,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
@@ -881,7 +885,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio_user"
|
name = "vfio_user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#eef6bec4d421f08ed1688fe67c5ea33aabbf5069"
|
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#2d96b90a7279547356ad8f83aaa3115ad5497302"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -897,9 +901,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.7.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84f81f436bca4541f4d33172e1202882c9d437db34ed17fc6d84c8ff2bde21f5"
|
checksum = "61957aeb36daf0b00b87fff9c10dd28a161bd35ab157553d340d183b3d8756e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -949,9 +953,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-queue"
|
name = "virtio-queue"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91aebb1df33db33cbf04d4c2445e4f78d0b0c8e65acfd16a4ee95ef63ca252f8"
|
checksum = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
@@ -988,12 +992,13 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.11.0"
|
version = "0.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d6ea57fe00f9086c59eeeb68e102dd611686bc3c28520fa465996d4d4bdce07"
|
checksum = "9dc276f0d00c17b9aeb584da0f1e1c673df0d183cc2539e3636ec8cbc5eae99b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
|
"thiserror",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1029,9 +1034,11 @@ dependencies = [
|
|||||||
"arch",
|
"arch",
|
||||||
"bitflags 2.3.3",
|
"bitflags 2.3.3",
|
||||||
"block",
|
"block",
|
||||||
|
"cfg-if",
|
||||||
"devices",
|
"devices",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
|
"flume",
|
||||||
"hypervisor",
|
"hypervisor",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-loader",
|
"linux-loader",
|
||||||
@@ -1066,9 +1073,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vmm-sys-util"
|
name = "vmm-sys-util"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46"
|
checksum = "48b7b084231214f7427041e4220d77dfe726897a6d41fddee450696e66ff2a29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1160,9 +1167,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3b9c234616391070b0b173963ebc65a9195068e7ed3731c6edac2ec45ebe106"
|
checksum = "20707b61725734c595e840fb3704378a0cd2b9c74cc9e6e20724838fc6a1e2f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
@@ -1170,9 +1177,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f7f3a471f98d0a61c34322fbbfd10c384b07687f680d4119813713f72308d91"
|
checksum = "56097d5b91d711293a42be9289403896b68654625021732067eac7a4ca388a1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ cargo-fuzz = true
|
|||||||
block = { path = "../block" }
|
block = { path = "../block" }
|
||||||
devices = { path = "../devices" }
|
devices = { path = "../devices" }
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
libc = "0.2.147"
|
libc = "0.2.148"
|
||||||
libfuzzer-sys = "0.4.6"
|
libfuzzer-sys = "0.4.7"
|
||||||
linux-loader = { version = "0.9.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" }
|
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
||||||
net_util = { path = "../net_util" }
|
net_util = { path = "../net_util" }
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
seccompiler = "0.3.0"
|
seccompiler = "0.3.0"
|
||||||
virtio-devices = { path = "../virtio-devices" }
|
virtio-devices = { path = "../virtio-devices" }
|
||||||
virtio-queue = "0.8.0"
|
virtio-queue = "0.9.0"
|
||||||
vmm = { path = "../vmm" }
|
vmm = { path = "../vmm" }
|
||||||
vmm-sys-util = "0.11.1"
|
vmm-sys-util = "0.11.2"
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const QUEUE_NUM: usize = 3;
|
|||||||
const QUEUE_SIZE: u16 = 64;
|
const QUEUE_SIZE: u16 = 64;
|
||||||
// Descriptor table alignment
|
// Descriptor table alignment
|
||||||
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
||||||
// Avalable ring alignment
|
// Available ring alignment
|
||||||
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
||||||
// Used ring alignment
|
// Used ring alignment
|
||||||
const USED_RING_ALIGN_SIZE: u64 = 4;
|
const USED_RING_ALIGN_SIZE: u64 = 4;
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ fuzz_target!(|bytes| {
|
|||||||
false,
|
false,
|
||||||
2,
|
2,
|
||||||
256,
|
256,
|
||||||
|
None,
|
||||||
SeccompAction::Allow,
|
SeccompAction::Allow,
|
||||||
None,
|
None,
|
||||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const IOVA_SPACE_SIZE: usize = (0xfeef_ffff - 0xfee0_0000) + 1;
|
|||||||
const QUEUE_SIZE: u16 = 256;
|
const QUEUE_SIZE: u16 = 256;
|
||||||
// Descriptor table alignment
|
// Descriptor table alignment
|
||||||
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
||||||
// Avalable ring alignment
|
// Available ring alignment
|
||||||
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
||||||
// Used ring alignment
|
// Used ring alignment
|
||||||
const USED_RING_ALIGN_SIZE: u64 = 4;
|
const USED_RING_ALIGN_SIZE: u64 = 4;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const VIRTIO_MEM_REGION_ADDRESS: u64 = 0;
|
|||||||
const QUEUE_SIZE: u16 = 64;
|
const QUEUE_SIZE: u16 = 64;
|
||||||
// Descriptor table alignment
|
// Descriptor table alignment
|
||||||
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
||||||
// Avalable ring alignment
|
// Available ring alignment
|
||||||
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
||||||
// Used ring alignment
|
// Used ring alignment
|
||||||
const USED_RING_ALIGN_SIZE: u64 = 4;
|
const USED_RING_ALIGN_SIZE: u64 = 4;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const MEM_SIZE: usize = 1 * 1024 * 1024;
|
|||||||
const QUEUE_SIZE: u16 = 256;
|
const QUEUE_SIZE: u16 = 256;
|
||||||
// Descriptor table alignment
|
// Descriptor table alignment
|
||||||
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
const DESC_TABLE_ALIGN_SIZE: u64 = 16;
|
||||||
// Avalable ring alignment
|
// Available ring alignment
|
||||||
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
const AVAIL_RING_ALIGN_SIZE: u64 = 2;
|
||||||
// Used ring alignment
|
// Used ring alignment
|
||||||
const USED_RING_ALIGN_SIZE: u64 = 4;
|
const USED_RING_ALIGN_SIZE: u64 = 4;
|
||||||
|
|||||||
@@ -8,22 +8,23 @@ license = "Apache-2.0 OR BSD-3-Clause"
|
|||||||
[features]
|
[features]
|
||||||
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
|
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
|
||||||
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"]
|
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"]
|
||||||
|
sev_snp = []
|
||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
kvm-ioctls = { version = "0.13.0", optional = true }
|
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 }
|
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 }
|
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
serde_with = { version = "3.0.0", default-features = false, features = ["macros"] }
|
serde_with = { version = "3.0.0", default-features = false, features = ["macros"] }
|
||||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||||
vm-memory = { version = "0.11.0", 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"] }
|
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use crate::arch::x86::Exception;
|
|||||||
// CMP affects OF, SF, ZF, AF, PF and CF
|
// CMP affects OF, SF, ZF, AF, PF and CF
|
||||||
const FLAGS_MASK: u64 = CF | PF | AF | ZF | SF | OF;
|
const FLAGS_MASK: u64 = CF | PF | AF | ZF | SF | OF;
|
||||||
|
|
||||||
// TODO: Switch to inline asm when that's stable. Executing CMP (or any arthimetic instructions)
|
// TODO: Switch to inline asm when that's stable. Executing CMP (or any arithmetic instructions)
|
||||||
// natively and extracting RFLAGS will be much faster and make the code simpler.
|
// natively and extracting RFLAGS will be much faster and make the code simpler.
|
||||||
fn calc_rflags_cpazso(op0: u64, op1: u64, op_size: usize) -> u64 {
|
fn calc_rflags_cpazso(op0: u64, op1: u64, op_size: usize) -> u64 {
|
||||||
let op_bits = op_size * 8;
|
let op_bits = op_size * 8;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ fn get_op<T: CpuStateManager>(
|
|||||||
insn: &Instruction,
|
insn: &Instruction,
|
||||||
op_index: u32,
|
op_index: u32,
|
||||||
op_size: usize,
|
op_size: usize,
|
||||||
state: &mut T,
|
state: &T,
|
||||||
platform: &mut dyn PlatformEmulator<CpuState = T>,
|
platform: &dyn PlatformEmulator<CpuState = T>,
|
||||||
) -> Result<u64, PlatformError> {
|
) -> Result<u64, PlatformError> {
|
||||||
if insn.op_count() < op_index + 1 {
|
if insn.op_count() < op_index + 1 {
|
||||||
return Err(PlatformError::InvalidOperand(anyhow!(
|
return Err(PlatformError::InvalidOperand(anyhow!(
|
||||||
@@ -124,7 +124,7 @@ fn memory_operand_address<T: CpuStateManager>(
|
|||||||
address += index;
|
address += index;
|
||||||
}
|
}
|
||||||
|
|
||||||
address += insn.memory_displacement64();
|
address = address.wrapping_add(insn.memory_displacement64());
|
||||||
|
|
||||||
// Translate to a linear address.
|
// Translate to a linear address.
|
||||||
state.linearize(insn.memory_segment(), address, write)
|
state.linearize(insn.memory_segment(), address, write)
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ pub enum HypervisorCpuError {
|
|||||||
UnknownTdxVmCall,
|
UnknownTdxVmCall,
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
///
|
///
|
||||||
/// Failed to intialize PMU
|
/// Failed to initialize PMU
|
||||||
///
|
///
|
||||||
#[error("Failed to initialize PMU")]
|
#[error("Failed to initialize PMU")]
|
||||||
InitializePmu,
|
InitializePmu,
|
||||||
@@ -252,6 +252,11 @@ pub enum HypervisorCpuError {
|
|||||||
///
|
///
|
||||||
#[error("Failed to get TSC frequency: {0}")]
|
#[error("Failed to get TSC frequency: {0}")]
|
||||||
GetTscKhz(#[source] anyhow::Error),
|
GetTscKhz(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
|
/// Error setting TSC frequency
|
||||||
|
///
|
||||||
|
#[error("Failed to set TSC frequency: {0}")]
|
||||||
|
SetTscKhz(#[source] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -447,6 +452,7 @@ pub trait Vcpu: Send + Sync {
|
|||||||
/// Return the list of initial MSR entries for a VCPU
|
/// Return the list of initial MSR entries for a VCPU
|
||||||
///
|
///
|
||||||
fn boot_msr_entries(&self) -> Vec<MsrEntry>;
|
fn boot_msr_entries(&self) -> Vec<MsrEntry>;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Get the frequency of the TSC if available
|
/// Get the frequency of the TSC if available
|
||||||
@@ -454,4 +460,11 @@ pub trait Vcpu: Send + Sync {
|
|||||||
fn tsc_khz(&self) -> Result<Option<u32>> {
|
fn tsc_khz(&self) -> Result<Option<u32>> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
///
|
||||||
|
/// Set the frequency of the TSC if available
|
||||||
|
///
|
||||||
|
fn set_tsc_khz(&self, _freq: u32) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ pub enum HypervisorError {
|
|||||||
///
|
///
|
||||||
#[error("Unsupported CPU:{0}")]
|
#[error("Unsupported CPU:{0}")]
|
||||||
UnsupportedCpu(#[source] anyhow::Error),
|
UnsupportedCpu(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
|
/// Launching a VM with unsupported VM Type
|
||||||
|
///
|
||||||
|
#[error("Unsupported VmType")]
|
||||||
|
UnsupportedVmType(),
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1205,7 +1205,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
off += std::mem::size_of::<u64>();
|
off += std::mem::size_of::<u64>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now moving on to floting point registers which are stored in the user_fpsimd_state in the kernel:
|
// Now moving on to floating point registers which are stored in the user_fpsimd_state in the kernel:
|
||||||
// https://elixir.free-electrons.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53
|
// https://elixir.free-electrons.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53
|
||||||
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
|
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
@@ -1890,6 +1890,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let vcpu_events = self.get_vcpu_events()?;
|
let vcpu_events = self.get_vcpu_events()?;
|
||||||
|
let tsc_khz = self.tsc_khz()?;
|
||||||
|
|
||||||
Ok(VcpuKvmState {
|
Ok(VcpuKvmState {
|
||||||
cpuid,
|
cpuid,
|
||||||
@@ -1902,6 +1903,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
xsave,
|
xsave,
|
||||||
xcrs,
|
xcrs,
|
||||||
mp_state,
|
mp_state,
|
||||||
|
tsc_khz,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
@@ -2004,6 +2006,10 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
self.set_lapic(&state.lapic_state)?;
|
self.set_lapic(&state.lapic_state)?;
|
||||||
self.set_fpu(&state.fpu)?;
|
self.set_fpu(&state.fpu)?;
|
||||||
|
|
||||||
|
if let Some(freq) = state.tsc_khz {
|
||||||
|
self.set_tsc_khz(freq)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to set all MSRs previously stored.
|
// Try to set all MSRs previously stored.
|
||||||
// If the number of MSRs set from SET_MSRS is different from the
|
// If the number of MSRs set from SET_MSRS is different from the
|
||||||
// expected amount, we fallback onto a slower method by setting MSRs
|
// expected amount, we fallback onto a slower method by setting MSRs
|
||||||
@@ -2186,6 +2192,23 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
Ok(v) => Ok(Some(v)),
|
Ok(v) => Ok(Some(v)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
///
|
||||||
|
/// Set the frequency of the TSC if available
|
||||||
|
///
|
||||||
|
fn set_tsc_khz(&self, freq: u32) -> cpu::Result<()> {
|
||||||
|
match self.fd.set_tsc_khz(freq) {
|
||||||
|
Err(e) => {
|
||||||
|
if e.errno() == libc::EIO {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(cpu::HypervisorCpuError::SetTscKhz(e.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KvmVcpu {
|
impl KvmVcpu {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ pub struct VcpuKvmState {
|
|||||||
pub xsave: Xsave,
|
pub xsave: Xsave,
|
||||||
pub xcrs: ExtendedControlRegisters,
|
pub xcrs: ExtendedControlRegisters,
|
||||||
pub mp_state: MpState,
|
pub mp_state: MpState,
|
||||||
|
pub tsc_khz: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StandardRegisters> for kvm_regs {
|
impl From<StandardRegisters> for kvm_regs {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ pub enum MpState {
|
|||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
Kvm(kvm_bindings::kvm_mp_state),
|
Kvm(kvm_bindings::kvm_mp_state),
|
||||||
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
Mshv, /* MSHV does not supprt MpState yet */
|
Mshv, /* MSHV does not support MpState yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -164,7 +164,7 @@ pub enum ClockData {
|
|||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
Kvm(kvm_bindings::kvm_clock_data),
|
Kvm(kvm_bindings::kvm_clock_data),
|
||||||
#[cfg(feature = "mshv")]
|
#[cfg(feature = "mshv")]
|
||||||
Mshv, /* MSHV does not supprt ClockData yet */
|
Mshv, /* MSHV does not support ClockData yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::vec_with_array_field;
|
|||||||
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
||||||
use crate::HypervisorType;
|
use crate::HypervisorType;
|
||||||
pub use mshv_bindings::*;
|
pub use mshv_bindings::*;
|
||||||
use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd};
|
use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
@@ -210,21 +210,15 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
fn hypervisor_type(&self) -> HypervisorType {
|
fn hypervisor_type(&self) -> HypervisorType {
|
||||||
HypervisorType::Mshv
|
HypervisorType::Mshv
|
||||||
}
|
}
|
||||||
/// Create a mshv vm object and return the object as Vm trait object
|
|
||||||
///
|
fn create_vm_with_type(&self, vm_type: u64) -> hypervisor::Result<Arc<dyn crate::Vm>> {
|
||||||
/// # Examples
|
let mshv_vm_type: VmType = match VmType::try_from(vm_type) {
|
||||||
///
|
Ok(vm_type) => vm_type,
|
||||||
/// ```
|
Err(_) => return Err(hypervisor::HypervisorError::UnsupportedVmType()),
|
||||||
/// # extern crate hypervisor;
|
};
|
||||||
/// # use hypervisor::mshv::MshvHypervisor;
|
|
||||||
/// use hypervisor::mshv::MshvVm;
|
|
||||||
/// let hypervisor = MshvHypervisor::new().unwrap();
|
|
||||||
/// let vm = hypervisor.create_vm().unwrap();
|
|
||||||
/// ```
|
|
||||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
|
||||||
let fd: VmFd;
|
let fd: VmFd;
|
||||||
loop {
|
loop {
|
||||||
match self.mshv.create_vm() {
|
match self.mshv.create_vm_with_type(mshv_vm_type) {
|
||||||
Ok(res) => fd = res,
|
Ok(res) => fd = res,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.errno() == libc::EINTR {
|
if e.errno() == libc::EINTR {
|
||||||
@@ -271,6 +265,22 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a mshv vm object and return the object as Vm trait object
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # extern crate hypervisor;
|
||||||
|
/// # use hypervisor::mshv::MshvHypervisor;
|
||||||
|
/// use hypervisor::mshv::MshvVm;
|
||||||
|
/// let hypervisor = MshvHypervisor::new().unwrap();
|
||||||
|
/// let vm = hypervisor.create_vm().unwrap();
|
||||||
|
/// ```
|
||||||
|
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||||
|
let vm_type = 0;
|
||||||
|
self.create_vm_with_type(vm_type)
|
||||||
|
}
|
||||||
///
|
///
|
||||||
/// Get the supported CpuID
|
/// Get the supported CpuID
|
||||||
///
|
///
|
||||||
@@ -562,6 +572,18 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
debug!("Exception Info {:?}", { info.exception_vector });
|
debug!("Exception Info {:?}", { info.exception_vector });
|
||||||
Ok(cpu::VmExit::Ignore)
|
Ok(cpu::VmExit::Ignore)
|
||||||
}
|
}
|
||||||
|
hv_message_type_HVMSG_X64_APIC_EOI => {
|
||||||
|
let info = x.to_apic_eoi_info().unwrap();
|
||||||
|
// The kernel should dispatch the EOI to the correct thread.
|
||||||
|
// Check the VP index is the same as the one we have.
|
||||||
|
assert!(info.vp_index == self.vp_index as u32);
|
||||||
|
// The interrupt vector in info is u32, but x86 only supports 256 vectors.
|
||||||
|
// There is no good way to recover from this if the hypervisor messes around.
|
||||||
|
// Just unwrap.
|
||||||
|
Ok(cpu::VmExit::IoapicEoi(
|
||||||
|
info.interrupt_vector.try_into().unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
exit => Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
exit => Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
||||||
"Unhandled VCPU exit {:?}",
|
"Unhandled VCPU exit {:?}",
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ pub trait Vm: Send + Sync + Any {
|
|||||||
/// Get dirty pages bitmap
|
/// Get dirty pages bitmap
|
||||||
fn get_dirty_log(&self, slot: u32, base_gpa: u64, memory_size: u64) -> Result<Vec<u64>>;
|
fn get_dirty_log(&self, slot: u32, base_gpa: u64, memory_size: u64) -> Result<Vec<u64>>;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
/// Initalize TDX on this VM
|
/// Initialize TDX on this VM
|
||||||
fn tdx_init(&self, _cpuid: &[CpuIdEntry], _max_vcpus: u32) -> Result<()> {
|
fn tdx_init(&self, _cpuid: &[CpuIdEntry], _max_vcpus: u32) -> Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ pub trait Vm: Send + Sync + Any {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
/// Initalize a TDX memory region for this VM
|
/// Initialize a TDX memory region for this VM
|
||||||
fn tdx_init_memory_region(
|
fn tdx_init_memory_region(
|
||||||
&self,
|
&self,
|
||||||
_host_address: u64,
|
_host_address: u64,
|
||||||
|
|||||||
@@ -7,22 +7,22 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
net_gen = { path = "../net_gen" }
|
net_gen = { path = "../net_gen" }
|
||||||
rate_limiter = { path = "../rate_limiter" }
|
rate_limiter = { path = "../rate_limiter" }
|
||||||
serde = "1.0.164"
|
serde = "1.0.168"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
versionize = "0.1.10"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = "0.2.0"
|
virtio-bindings = "0.2.0"
|
||||||
virtio-queue = "0.8.0"
|
virtio-queue = "0.9.0"
|
||||||
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
pnet = "0.33.0"
|
pnet = "0.34.0"
|
||||||
pnet_datalink = "0.33.0"
|
pnet_datalink = "0.34.0"
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl TxVirtio {
|
|||||||
pub fn process_desc_chain(
|
pub fn process_desc_chain(
|
||||||
&mut self,
|
&mut self,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
tap: &mut Tap,
|
tap: &Tap,
|
||||||
queue: &mut Queue,
|
queue: &mut Queue,
|
||||||
rate_limiter: &mut Option<RateLimiter>,
|
rate_limiter: &mut Option<RateLimiter>,
|
||||||
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
||||||
@@ -64,9 +64,9 @@ impl TxVirtio {
|
|||||||
.memory()
|
.memory()
|
||||||
.get_slice(desc_addr, desc.len() as usize)
|
.get_slice(desc_addr, desc.len() as usize)
|
||||||
.map_err(NetQueuePairError::GuestMemory)?
|
.map_err(NetQueuePairError::GuestMemory)?
|
||||||
.as_ptr();
|
.ptr_guard_mut();
|
||||||
let iovec = libc::iovec {
|
let iovec = libc::iovec {
|
||||||
iov_base: buf as *mut libc::c_void,
|
iov_base: buf.as_ptr() as *mut libc::c_void,
|
||||||
iov_len: desc.len() as libc::size_t,
|
iov_len: desc.len() as libc::size_t,
|
||||||
};
|
};
|
||||||
iovecs.push(iovec);
|
iovecs.push(iovec);
|
||||||
@@ -164,7 +164,7 @@ impl RxVirtio {
|
|||||||
pub fn process_desc_chain(
|
pub fn process_desc_chain(
|
||||||
&mut self,
|
&mut self,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
tap: &mut Tap,
|
tap: &Tap,
|
||||||
queue: &mut Queue,
|
queue: &mut Queue,
|
||||||
rate_limiter: &mut Option<RateLimiter>,
|
rate_limiter: &mut Option<RateLimiter>,
|
||||||
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
||||||
@@ -203,9 +203,9 @@ impl RxVirtio {
|
|||||||
.memory()
|
.memory()
|
||||||
.get_slice(desc_addr, desc.len() as usize)
|
.get_slice(desc_addr, desc.len() as usize)
|
||||||
.map_err(NetQueuePairError::GuestMemory)?
|
.map_err(NetQueuePairError::GuestMemory)?
|
||||||
.as_ptr();
|
.ptr_guard_mut();
|
||||||
let iovec = libc::iovec {
|
let iovec = libc::iovec {
|
||||||
iov_base: buf as *mut libc::c_void,
|
iov_base: buf.as_ptr() as *mut libc::c_void,
|
||||||
iov_len: desc.len() as libc::size_t,
|
iov_len: desc.len() as libc::size_t,
|
||||||
};
|
};
|
||||||
iovecs.push(iovec);
|
iovecs.push(iovec);
|
||||||
@@ -357,7 +357,7 @@ impl NetQueuePair {
|
|||||||
) -> Result<bool, NetQueuePairError> {
|
) -> Result<bool, NetQueuePairError> {
|
||||||
let tx_tap_retry = self.tx.process_desc_chain(
|
let tx_tap_retry = self.tx.process_desc_chain(
|
||||||
mem,
|
mem,
|
||||||
&mut self.tap,
|
&self.tap,
|
||||||
queue,
|
queue,
|
||||||
&mut self.tx_rate_limiter,
|
&mut self.tx_rate_limiter,
|
||||||
self.access_platform.as_ref(),
|
self.access_platform.as_ref(),
|
||||||
@@ -407,7 +407,7 @@ impl NetQueuePair {
|
|||||||
) -> Result<bool, NetQueuePairError> {
|
) -> Result<bool, NetQueuePairError> {
|
||||||
self.rx_desc_avail = !self.rx.process_desc_chain(
|
self.rx_desc_avail = !self.rx.process_desc_chain(
|
||||||
mem,
|
mem,
|
||||||
&mut self.tap,
|
&self.tap,
|
||||||
queue,
|
queue,
|
||||||
&mut self.rx_rate_limiter,
|
&mut self.rx_rate_limiter,
|
||||||
self.access_platform.as_ref(),
|
self.access_platform.as_ref(),
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ impl Tap {
|
|||||||
let mut ifreq: net_gen::ifreq = Default::default();
|
let mut ifreq: net_gen::ifreq = Default::default();
|
||||||
|
|
||||||
// Get current config including name
|
// Get current config including name
|
||||||
// SAFETY: IOCTL with correct arugments
|
// SAFETY: IOCTL with correct arguments
|
||||||
unsafe { Self::ioctl_with_mut_ref(&tap_file, net_gen::TUNGETIFF(), &mut ifreq)? };
|
unsafe { Self::ioctl_with_mut_ref(&tap_file, net_gen::TUNGETIFF(), &mut ifreq)? };
|
||||||
|
|
||||||
// SAFETY: We only access one field of the ifru union
|
// SAFETY: We only access one field of the ifru union
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ kvm = ["vfio-ioctls/kvm"]
|
|||||||
mshv = ["vfio-ioctls/mshv"]
|
mshv = ["vfio-ioctls/mshv"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
||||||
@@ -18,13 +18,13 @@ vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", defau
|
|||||||
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
||||||
|
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
serde = { version = "1.0.164", features = ["derive"] }
|
serde = { version = "1.0.168", features = ["derive"] }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
versionize = "0.1.10"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { version = "0.11.0", 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-migration = { path = "../vm-migration" }
|
||||||
|
|||||||
@@ -265,10 +265,10 @@ pub enum PciExpressCapabilityId {
|
|||||||
VendorSpecificExtendedCapability = 0x000b,
|
VendorSpecificExtendedCapability = 0x000b,
|
||||||
ConfigurationAccessCorrelation = 0x000c,
|
ConfigurationAccessCorrelation = 0x000c,
|
||||||
AccessControlServices = 0x000d,
|
AccessControlServices = 0x000d,
|
||||||
AlternativeRoutingIdentificationIntepretation = 0x000e,
|
AlternativeRoutingIdentificationInterpretation = 0x000e,
|
||||||
AddressTranslationServices = 0x000f,
|
AddressTranslationServices = 0x000f,
|
||||||
SingleRootIoVirtualization = 0x0010,
|
SingleRootIoVirtualization = 0x0010,
|
||||||
DeprecatedMultiRootIoVirtualzation = 0x0011,
|
DeprecatedMultiRootIoVirtualization = 0x0011,
|
||||||
Multicast = 0x0012,
|
Multicast = 0x0012,
|
||||||
PageRequestInterface = 0x0013,
|
PageRequestInterface = 0x0013,
|
||||||
ReservedForAmd = 0x0014,
|
ReservedForAmd = 0x0014,
|
||||||
@@ -279,7 +279,7 @@ pub enum PciExpressCapabilityId {
|
|||||||
SecondaryPciExpress = 0x0019,
|
SecondaryPciExpress = 0x0019,
|
||||||
ProtocolMultiplexing = 0x001a,
|
ProtocolMultiplexing = 0x001a,
|
||||||
ProcessAddressSpaceId = 0x001b,
|
ProcessAddressSpaceId = 0x001b,
|
||||||
LnRequestor = 0x001c,
|
LnRequester = 0x001c,
|
||||||
DownstreamPortContainment = 0x001d,
|
DownstreamPortContainment = 0x001d,
|
||||||
L1PmSubstates = 0x001e,
|
L1PmSubstates = 0x001e,
|
||||||
PrecisionTimeMeasurement = 0x001f,
|
PrecisionTimeMeasurement = 0x001f,
|
||||||
@@ -319,10 +319,10 @@ impl From<u16> for PciExpressCapabilityId {
|
|||||||
0x000b => PciExpressCapabilityId::VendorSpecificExtendedCapability,
|
0x000b => PciExpressCapabilityId::VendorSpecificExtendedCapability,
|
||||||
0x000c => PciExpressCapabilityId::ConfigurationAccessCorrelation,
|
0x000c => PciExpressCapabilityId::ConfigurationAccessCorrelation,
|
||||||
0x000d => PciExpressCapabilityId::AccessControlServices,
|
0x000d => PciExpressCapabilityId::AccessControlServices,
|
||||||
0x000e => PciExpressCapabilityId::AlternativeRoutingIdentificationIntepretation,
|
0x000e => PciExpressCapabilityId::AlternativeRoutingIdentificationInterpretation,
|
||||||
0x000f => PciExpressCapabilityId::AddressTranslationServices,
|
0x000f => PciExpressCapabilityId::AddressTranslationServices,
|
||||||
0x0010 => PciExpressCapabilityId::SingleRootIoVirtualization,
|
0x0010 => PciExpressCapabilityId::SingleRootIoVirtualization,
|
||||||
0x0011 => PciExpressCapabilityId::DeprecatedMultiRootIoVirtualzation,
|
0x0011 => PciExpressCapabilityId::DeprecatedMultiRootIoVirtualization,
|
||||||
0x0012 => PciExpressCapabilityId::Multicast,
|
0x0012 => PciExpressCapabilityId::Multicast,
|
||||||
0x0013 => PciExpressCapabilityId::PageRequestInterface,
|
0x0013 => PciExpressCapabilityId::PageRequestInterface,
|
||||||
0x0014 => PciExpressCapabilityId::ReservedForAmd,
|
0x0014 => PciExpressCapabilityId::ReservedForAmd,
|
||||||
@@ -333,7 +333,7 @@ impl From<u16> for PciExpressCapabilityId {
|
|||||||
0x0019 => PciExpressCapabilityId::SecondaryPciExpress,
|
0x0019 => PciExpressCapabilityId::SecondaryPciExpress,
|
||||||
0x001a => PciExpressCapabilityId::ProtocolMultiplexing,
|
0x001a => PciExpressCapabilityId::ProtocolMultiplexing,
|
||||||
0x001b => PciExpressCapabilityId::ProcessAddressSpaceId,
|
0x001b => PciExpressCapabilityId::ProcessAddressSpaceId,
|
||||||
0x001c => PciExpressCapabilityId::LnRequestor,
|
0x001c => PciExpressCapabilityId::LnRequester,
|
||||||
0x001d => PciExpressCapabilityId::DownstreamPortContainment,
|
0x001d => PciExpressCapabilityId::DownstreamPortContainment,
|
||||||
0x001e => PciExpressCapabilityId::L1PmSubstates,
|
0x001e => PciExpressCapabilityId::L1PmSubstates,
|
||||||
0x001f => PciExpressCapabilityId::PrecisionTimeMeasurement,
|
0x001f => PciExpressCapabilityId::PrecisionTimeMeasurement,
|
||||||
|
|||||||
@@ -502,8 +502,8 @@ impl VfioCommon {
|
|||||||
Ok(vfio_common)
|
Ok(vfio_common)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In case msix table offset is not page size aligned, we need do some fixup to achive it.
|
/// In case msix table offset is not page size aligned, we need do some fixup to achieve it.
|
||||||
/// Becuse we don't want the MMIO RW region and trap region overlap each other.
|
/// Because we don't want the MMIO RW region and trap region overlap each other.
|
||||||
fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
|
fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
|
||||||
if let Some(msix) = self.interrupt.msix.as_mut() {
|
if let Some(msix) = self.interrupt.msix.as_mut() {
|
||||||
let msix_cap = &mut msix.cap;
|
let msix_cap = &mut msix.cap;
|
||||||
@@ -911,7 +911,7 @@ impl VfioCommon {
|
|||||||
let cap_next: u16 = ((ext_cap_hdr >> 20) & 0xfff) as u16;
|
let cap_next: u16 = ((ext_cap_hdr >> 20) & 0xfff) as u16;
|
||||||
|
|
||||||
match PciExpressCapabilityId::from(cap_id) {
|
match PciExpressCapabilityId::from(cap_id) {
|
||||||
PciExpressCapabilityId::AlternativeRoutingIdentificationIntepretation
|
PciExpressCapabilityId::AlternativeRoutingIdentificationInterpretation
|
||||||
| PciExpressCapabilityId::ResizeableBar
|
| PciExpressCapabilityId::ResizeableBar
|
||||||
| PciExpressCapabilityId::SingleRootIoVirtualization => {
|
| PciExpressCapabilityId::SingleRootIoVirtualization => {
|
||||||
let reg_idx = (current_offset / 4) as usize;
|
let reg_idx = (current_offset / 4) as usize;
|
||||||
@@ -1411,7 +1411,7 @@ impl VfioPciDevice {
|
|||||||
// around them, leading to a list of sparse areas.
|
// around them, leading to a list of sparse areas.
|
||||||
// We want to make sure we will still trap MMIO accesses
|
// We want to make sure we will still trap MMIO accesses
|
||||||
// to these MSI-X specific ranges. If these region don't align
|
// to these MSI-X specific ranges. If these region don't align
|
||||||
// with pagesize, we can achive it by enlarging its range.
|
// with pagesize, we can achieve it by enlarging its range.
|
||||||
//
|
//
|
||||||
// Using a BtreeMap as the list provided through the iterator is sorted
|
// Using a BtreeMap as the list provided through the iterator is sorted
|
||||||
// by key. This ensures proper split of the whole region.
|
// by key. This ensures proper split of the whole region.
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ build = "../build.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
argh = "0.1.9"
|
argh = "0.1.9"
|
||||||
dirs = "5.0.0"
|
dirs = "5.0.0"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
test_infra = { path = "../test_infra" }
|
test_infra = { path = "../test_infra" }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|||||||
@@ -46,9 +46,11 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Mutex;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{fmt, io};
|
|
||||||
use vmm_sys_util::timerfd::TimerFd;
|
use vmm_sys_util::timerfd::TimerFd;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -271,27 +273,27 @@ pub enum BucketUpdate {
|
|||||||
/// implementation. These events are meant to be consumed by the user of this struct.
|
/// implementation. These events are meant to be consumed by the user of this struct.
|
||||||
/// On each such event, the user must call the `event_handler()` method.
|
/// On each such event, the user must call the `event_handler()` method.
|
||||||
pub struct RateLimiter {
|
pub struct RateLimiter {
|
||||||
|
inner: Mutex<RateLimiterInner>,
|
||||||
|
|
||||||
|
// Internal flag that quickly determines timer state.
|
||||||
|
timer_active: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RateLimiterInner {
|
||||||
bandwidth: Option<TokenBucket>,
|
bandwidth: Option<TokenBucket>,
|
||||||
ops: Option<TokenBucket>,
|
ops: Option<TokenBucket>,
|
||||||
|
|
||||||
timer_fd: TimerFd,
|
timer_fd: TimerFd,
|
||||||
// Internal flag that quickly determines timer state.
|
|
||||||
timer_active: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for RateLimiter {
|
impl RateLimiterInner {
|
||||||
fn eq(&self, other: &RateLimiter) -> bool {
|
// Arm the timer of the rate limiter with the provided `Duration` (which will fire only once).
|
||||||
self.bandwidth == other.bandwidth && self.ops == other.ops
|
fn activate_timer(&mut self, dur: Duration, flag: &AtomicBool) {
|
||||||
}
|
// Panic when failing to arm the timer (same handling in crate TimerFd::set_state())
|
||||||
}
|
self.timer_fd
|
||||||
|
.reset(dur, None)
|
||||||
impl fmt::Debug for RateLimiter {
|
.expect("Can't arm the timer (unexpected 'timerfd_settime' failure).");
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
flag.store(true, Ordering::Relaxed)
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"RateLimiter {{ bandwidth: {:?}, ops: {:?} }}",
|
|
||||||
self.bandwidth, self.ops
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,35 +357,28 @@ impl RateLimiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(RateLimiter {
|
Ok(RateLimiter {
|
||||||
bandwidth: bytes_token_bucket,
|
inner: Mutex::new(RateLimiterInner {
|
||||||
ops: ops_token_bucket,
|
bandwidth: bytes_token_bucket,
|
||||||
timer_fd,
|
ops: ops_token_bucket,
|
||||||
timer_active: false,
|
timer_fd,
|
||||||
|
}),
|
||||||
|
timer_active: AtomicBool::new(false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arm the timer of the rate limiter with the provided `Duration` (which will fire only once).
|
|
||||||
fn activate_timer(&mut self, dur: Duration) {
|
|
||||||
// Panic when failing to arm the timer (same handling in crate TimerFd::set_state())
|
|
||||||
self.timer_fd
|
|
||||||
.reset(dur, None)
|
|
||||||
.expect("Can't arm the timer (unexpected 'timerfd_settime' failure).");
|
|
||||||
self.timer_active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to consume tokens and returns whether that is possible.
|
/// Attempts to consume tokens and returns whether that is possible.
|
||||||
///
|
///
|
||||||
/// If rate limiting is disabled on provided `token_type`, this function will always succeed.
|
/// If rate limiting is disabled on provided `token_type`, this function will always succeed.
|
||||||
pub fn consume(&mut self, tokens: u64, token_type: TokenType) -> bool {
|
pub fn consume(&self, tokens: u64, token_type: TokenType) -> bool {
|
||||||
// If the timer is active, we can't consume tokens from any bucket and the function fails.
|
// If the timer is active, we can't consume tokens from any bucket and the function fails.
|
||||||
if self.timer_active {
|
if self.is_blocked() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
// Identify the required token bucket.
|
// Identify the required token bucket.
|
||||||
let token_bucket = match token_type {
|
let token_bucket = match token_type {
|
||||||
TokenType::Bytes => self.bandwidth.as_mut(),
|
TokenType::Bytes => guard.bandwidth.as_mut(),
|
||||||
TokenType::Ops => self.ops.as_mut(),
|
TokenType::Ops => guard.ops.as_mut(),
|
||||||
};
|
};
|
||||||
// Try to consume from the token bucket.
|
// Try to consume from the token bucket.
|
||||||
if let Some(bucket) = token_bucket {
|
if let Some(bucket) = token_bucket {
|
||||||
@@ -393,8 +388,8 @@ impl RateLimiter {
|
|||||||
// register a timer to replenish the bucket and resume processing;
|
// register a timer to replenish the bucket and resume processing;
|
||||||
// make sure there is only one running timer for this limiter.
|
// make sure there is only one running timer for this limiter.
|
||||||
BucketReduction::Failure => {
|
BucketReduction::Failure => {
|
||||||
if !self.timer_active {
|
if !self.is_blocked() {
|
||||||
self.activate_timer(TIMER_REFILL_DUR);
|
guard.activate_timer(TIMER_REFILL_DUR, &self.timer_active);
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -409,7 +404,10 @@ impl RateLimiter {
|
|||||||
// order to enforce the bandwidth limit we need to prevent
|
// order to enforce the bandwidth limit we need to prevent
|
||||||
// further calls to the rate limiter for
|
// further calls to the rate limiter for
|
||||||
// `ratio * refill_time` milliseconds.
|
// `ratio * refill_time` milliseconds.
|
||||||
self.activate_timer(Duration::from_millis((ratio * refill_time as f64) as u64));
|
guard.activate_timer(
|
||||||
|
Duration::from_millis((ratio * refill_time as f64) as u64),
|
||||||
|
&self.timer_active,
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,11 +422,12 @@ impl RateLimiter {
|
|||||||
///
|
///
|
||||||
/// Can be used to *manually* add tokens to a bucket. Useful for reverting a
|
/// Can be used to *manually* add tokens to a bucket. Useful for reverting a
|
||||||
/// `consume()` if needed.
|
/// `consume()` if needed.
|
||||||
pub fn manual_replenish(&mut self, tokens: u64, token_type: TokenType) {
|
pub fn manual_replenish(&self, tokens: u64, token_type: TokenType) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
// Identify the required token bucket.
|
// Identify the required token bucket.
|
||||||
let token_bucket = match token_type {
|
let token_bucket = match token_type {
|
||||||
TokenType::Bytes => self.bandwidth.as_mut(),
|
TokenType::Bytes => guard.bandwidth.as_mut(),
|
||||||
TokenType::Ops => self.ops.as_mut(),
|
TokenType::Ops => guard.ops.as_mut(),
|
||||||
};
|
};
|
||||||
// Add tokens to the token bucket.
|
// Add tokens to the token bucket.
|
||||||
if let Some(bucket) = token_bucket {
|
if let Some(bucket) = token_bucket {
|
||||||
@@ -442,7 +441,7 @@ impl RateLimiter {
|
|||||||
/// budget for it.
|
/// budget for it.
|
||||||
/// An event will be generated on the exported FD when the limiter 'unblocks'.
|
/// An event will be generated on the exported FD when the limiter 'unblocks'.
|
||||||
pub fn is_blocked(&self) -> bool {
|
pub fn is_blocked(&self) -> bool {
|
||||||
self.timer_active
|
self.timer_active.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function needs to be called every time there is an event on the
|
/// This function needs to be called every time there is an event on the
|
||||||
@@ -451,11 +450,12 @@ impl RateLimiter {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If the rate limiter is disabled or is not blocked, an error is returned.
|
/// If the rate limiter is disabled or is not blocked, an error is returned.
|
||||||
pub fn event_handler(&mut self) -> Result<(), Error> {
|
pub fn event_handler(&self) -> Result<(), Error> {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
loop {
|
loop {
|
||||||
// Note: As we manually added the `O_NONBLOCK` flag to the FD, the following
|
// Note: As we manually added the `O_NONBLOCK` flag to the FD, the following
|
||||||
// `timer_fd::wait()` won't block (which is different from its default behavior.)
|
// `timer_fd::wait()` won't block (which is different from its default behavior.)
|
||||||
match self.timer_fd.wait() {
|
match guard.timer_fd.wait() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err: std::io::Error = e.into();
|
let err: std::io::Error = e.into();
|
||||||
match err.kind() {
|
match err.kind() {
|
||||||
@@ -469,7 +469,7 @@ impl RateLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.timer_active = false;
|
self.timer_active.store(false, Ordering::Relaxed);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,27 +479,18 @@ impl RateLimiter {
|
|||||||
/// Updates the parameters of the token buckets associated with this RateLimiter.
|
/// Updates the parameters of the token buckets associated with this RateLimiter.
|
||||||
// TODO: Please note that, right now, the buckets become full after being updated.
|
// TODO: Please note that, right now, the buckets become full after being updated.
|
||||||
pub fn update_buckets(&mut self, bytes: BucketUpdate, ops: BucketUpdate) {
|
pub fn update_buckets(&mut self, bytes: BucketUpdate, ops: BucketUpdate) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
match bytes {
|
match bytes {
|
||||||
BucketUpdate::Disabled => self.bandwidth = None,
|
BucketUpdate::Disabled => guard.bandwidth = None,
|
||||||
BucketUpdate::Update(tb) => self.bandwidth = Some(tb),
|
BucketUpdate::Update(tb) => guard.bandwidth = Some(tb),
|
||||||
BucketUpdate::None => (),
|
BucketUpdate::None => (),
|
||||||
};
|
};
|
||||||
match ops {
|
match ops {
|
||||||
BucketUpdate::Disabled => self.ops = None,
|
BucketUpdate::Disabled => guard.ops = None,
|
||||||
BucketUpdate::Update(tb) => self.ops = Some(tb),
|
BucketUpdate::Update(tb) => guard.ops = Some(tb),
|
||||||
BucketUpdate::None => (),
|
BucketUpdate::None => (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable view of the inner bandwidth token bucket.
|
|
||||||
pub fn bandwidth(&self) -> Option<&TokenBucket> {
|
|
||||||
self.bandwidth.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an immutable view of the inner ops token bucket.
|
|
||||||
pub fn ops(&self) -> Option<&TokenBucket> {
|
|
||||||
self.ops.as_ref()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for RateLimiter {
|
impl AsRawFd for RateLimiter {
|
||||||
@@ -510,7 +501,8 @@ impl AsRawFd for RateLimiter {
|
|||||||
/// Will return a negative value if rate limiting is disabled on both
|
/// Will return a negative value if rate limiting is disabled on both
|
||||||
/// token types.
|
/// token types.
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.timer_fd.as_raw_fd()
|
let guard = self.inner.lock().unwrap();
|
||||||
|
guard.timer_fd.as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,6 +517,7 @@ impl Default for RateLimiter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::fmt;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -557,11 +550,33 @@ pub(crate) mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RateLimiter {
|
impl RateLimiter {
|
||||||
fn get_token_bucket(&self, token_type: TokenType) -> Option<&TokenBucket> {
|
pub fn bandwidth(&self) -> Option<TokenBucket> {
|
||||||
match token_type {
|
let guard = self.inner.lock().unwrap();
|
||||||
TokenType::Bytes => self.bandwidth.as_ref(),
|
guard.bandwidth.clone()
|
||||||
TokenType::Ops => self.ops.as_ref(),
|
}
|
||||||
}
|
|
||||||
|
pub fn ops(&self) -> Option<TokenBucket> {
|
||||||
|
let guard = self.inner.lock().unwrap();
|
||||||
|
guard.ops.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for RateLimiter {
|
||||||
|
fn eq(&self, other: &RateLimiter) -> bool {
|
||||||
|
let self_guard = self.inner.lock().unwrap();
|
||||||
|
let other_guard = other.inner.lock().unwrap();
|
||||||
|
self_guard.bandwidth == other_guard.bandwidth && self_guard.ops == other_guard.ops
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for RateLimiter {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let guard = self.inner.lock().unwrap();
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"RateLimiter {{ bandwidth: {:?}, ops: {:?} }}",
|
||||||
|
guard.bandwidth, guard.ops
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +655,7 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_default() {
|
fn test_rate_limiter_default() {
|
||||||
let mut l = RateLimiter::default();
|
let l = RateLimiter::default();
|
||||||
|
|
||||||
// limiter should not be blocked
|
// limiter should not be blocked
|
||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
@@ -659,14 +674,13 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_new() {
|
fn test_rate_limiter_new() {
|
||||||
let l = RateLimiter::new(1000, 1001, 1002, 1003, 1004, 1005).unwrap();
|
let l = RateLimiter::new(1000, 1001, 1002, 1003, 1004, 1005).unwrap();
|
||||||
|
let bw = l.bandwidth().unwrap();
|
||||||
let bw = l.bandwidth.unwrap();
|
|
||||||
assert_eq!(bw.capacity(), 1000);
|
assert_eq!(bw.capacity(), 1000);
|
||||||
assert_eq!(bw.one_time_burst(), 1001);
|
assert_eq!(bw.one_time_burst(), 1001);
|
||||||
assert_eq!(bw.refill_time_ms(), 1002);
|
assert_eq!(bw.refill_time_ms(), 1002);
|
||||||
assert_eq!(bw.budget(), 1000);
|
assert_eq!(bw.budget(), 1000);
|
||||||
|
|
||||||
let ops = l.ops.unwrap();
|
let ops = l.ops().unwrap();
|
||||||
assert_eq!(ops.capacity(), 1003);
|
assert_eq!(ops.capacity(), 1003);
|
||||||
assert_eq!(ops.one_time_burst(), 1004);
|
assert_eq!(ops.one_time_burst(), 1004);
|
||||||
assert_eq!(ops.refill_time_ms(), 1005);
|
assert_eq!(ops.refill_time_ms(), 1005);
|
||||||
@@ -676,20 +690,20 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_manual_replenish() {
|
fn test_rate_limiter_manual_replenish() {
|
||||||
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
||||||
let mut l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
let l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||||
|
|
||||||
// consume 123 bytes
|
// consume 123 bytes
|
||||||
assert!(l.consume(123, TokenType::Bytes));
|
assert!(l.consume(123, TokenType::Bytes));
|
||||||
l.manual_replenish(23, TokenType::Bytes);
|
l.manual_replenish(23, TokenType::Bytes);
|
||||||
{
|
{
|
||||||
let bytes_tb = l.get_token_bucket(TokenType::Bytes).unwrap();
|
let bytes_tb = l.bandwidth().unwrap();
|
||||||
assert_eq!(bytes_tb.budget(), 900);
|
assert_eq!(bytes_tb.budget(), 900);
|
||||||
}
|
}
|
||||||
// consume 123 ops
|
// consume 123 ops
|
||||||
assert!(l.consume(123, TokenType::Ops));
|
assert!(l.consume(123, TokenType::Ops));
|
||||||
l.manual_replenish(23, TokenType::Ops);
|
l.manual_replenish(23, TokenType::Ops);
|
||||||
{
|
{
|
||||||
let bytes_tb = l.get_token_bucket(TokenType::Ops).unwrap();
|
let bytes_tb = l.ops().unwrap();
|
||||||
assert_eq!(bytes_tb.budget(), 900);
|
assert_eq!(bytes_tb.budget(), 900);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,7 +711,7 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_bandwidth() {
|
fn test_rate_limiter_bandwidth() {
|
||||||
// rate limiter with limit of 1000 bytes/s
|
// rate limiter with limit of 1000 bytes/s
|
||||||
let mut l = RateLimiter::new(1000, 0, 1000, 0, 0, 0).unwrap();
|
let l = RateLimiter::new(1000, 0, 1000, 0, 0, 0).unwrap();
|
||||||
|
|
||||||
// limiter should not be blocked
|
// limiter should not be blocked
|
||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
@@ -730,7 +744,7 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_ops() {
|
fn test_rate_limiter_ops() {
|
||||||
// rate limiter with limit of 1000 ops/s
|
// rate limiter with limit of 1000 ops/s
|
||||||
let mut l = RateLimiter::new(0, 0, 0, 1000, 0, 1000).unwrap();
|
let l = RateLimiter::new(0, 0, 0, 1000, 0, 1000).unwrap();
|
||||||
|
|
||||||
// limiter should not be blocked
|
// limiter should not be blocked
|
||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
@@ -763,7 +777,7 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_full() {
|
fn test_rate_limiter_full() {
|
||||||
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
||||||
let mut l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
let l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||||
|
|
||||||
// limiter should not be blocked
|
// limiter should not be blocked
|
||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
@@ -799,7 +813,7 @@ pub(crate) mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rate_limiter_overconsumption() {
|
fn test_rate_limiter_overconsumption() {
|
||||||
// initialize the rate limiter
|
// initialize the rate limiter
|
||||||
let mut l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
let l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||||
// try to consume 2.5x the bucket size
|
// try to consume 2.5x the bucket size
|
||||||
// we are "borrowing" 1.5x the bucket size in tokens since
|
// we are "borrowing" 1.5x the bucket size in tokens since
|
||||||
// the bucket is full
|
// the bucket is full
|
||||||
@@ -818,7 +832,7 @@ pub(crate) mod tests {
|
|||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
|
|
||||||
// reset the rate limiter
|
// reset the rate limiter
|
||||||
let mut l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
let l = RateLimiter::new(1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||||
// try to consume 1.5x the bucket size
|
// try to consume 1.5x the bucket size
|
||||||
// we are "borrowing" 1.5x the bucket size in tokens since
|
// we are "borrowing" 1.5x the bucket size in tokens since
|
||||||
// the bucket is full, should arm the timer to 0.5x replenish
|
// the bucket is full, should arm the timer to 0.5x replenish
|
||||||
@@ -846,7 +860,7 @@ pub(crate) mod tests {
|
|||||||
assert!(!l.consume(100, TokenType::Bytes));
|
assert!(!l.consume(100, TokenType::Bytes));
|
||||||
|
|
||||||
// after waiting out the full duration, rate limiter should be
|
// after waiting out the full duration, rate limiter should be
|
||||||
// availale again
|
// available again
|
||||||
thread::sleep(Duration::from_millis(200));
|
thread::sleep(Duration::from_millis(200));
|
||||||
assert!(l.event_handler().is_ok());
|
assert!(l.event_handler().is_ok());
|
||||||
assert!(!l.is_blocked());
|
assert!(!l.is_blocked());
|
||||||
@@ -857,12 +871,12 @@ pub(crate) mod tests {
|
|||||||
fn test_update_buckets() {
|
fn test_update_buckets() {
|
||||||
let mut x = RateLimiter::new(1000, 2000, 1000, 10, 20, 1000).unwrap();
|
let mut x = RateLimiter::new(1000, 2000, 1000, 10, 20, 1000).unwrap();
|
||||||
|
|
||||||
let initial_bw = x.bandwidth.clone();
|
let initial_bw = x.bandwidth();
|
||||||
let initial_ops = x.ops.clone();
|
let initial_ops = x.ops();
|
||||||
|
|
||||||
x.update_buckets(BucketUpdate::None, BucketUpdate::None);
|
x.update_buckets(BucketUpdate::None, BucketUpdate::None);
|
||||||
assert_eq!(x.bandwidth, initial_bw);
|
assert_eq!(x.bandwidth(), initial_bw);
|
||||||
assert_eq!(x.ops, initial_ops);
|
assert_eq!(x.ops(), initial_ops);
|
||||||
|
|
||||||
let new_bw = TokenBucket::new(123, 0, 57).unwrap();
|
let new_bw = TokenBucket::new(123, 0, 57).unwrap();
|
||||||
let new_ops = TokenBucket::new(321, 12346, 89).unwrap();
|
let new_ops = TokenBucket::new(321, 12346, 89).unwrap();
|
||||||
@@ -871,18 +885,21 @@ pub(crate) mod tests {
|
|||||||
BucketUpdate::Update(new_ops.clone()),
|
BucketUpdate::Update(new_ops.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// We have manually adjust the last_update field, because it changes when update_buckets()
|
{
|
||||||
// constructs new buckets (and thus gets a different value for last_update). We do this so
|
let mut guard = x.inner.lock().unwrap();
|
||||||
// it makes sense to test the following assertions.
|
// We have manually adjust the last_update field, because it changes when update_buckets()
|
||||||
x.bandwidth.as_mut().unwrap().last_update = new_bw.last_update;
|
// constructs new buckets (and thus gets a different value for last_update). We do this so
|
||||||
x.ops.as_mut().unwrap().last_update = new_ops.last_update;
|
// it makes sense to test the following assertions.
|
||||||
|
guard.bandwidth.as_mut().unwrap().last_update = new_bw.last_update;
|
||||||
|
guard.ops.as_mut().unwrap().last_update = new_ops.last_update;
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(x.bandwidth, Some(new_bw));
|
assert_eq!(x.bandwidth(), Some(new_bw));
|
||||||
assert_eq!(x.ops, Some(new_ops));
|
assert_eq!(x.ops(), Some(new_ops));
|
||||||
|
|
||||||
x.update_buckets(BucketUpdate::Disabled, BucketUpdate::Disabled);
|
x.update_buckets(BucketUpdate::Disabled, BucketUpdate::Disabled);
|
||||||
assert_eq!(x.bandwidth, None);
|
assert_eq!(x.bandwidth(), None);
|
||||||
assert_eq!(x.ops, None);
|
assert_eq!(x.ops(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
184
release-notes.md
184
release-notes.md
@@ -1,20 +1,27 @@
|
|||||||
|
- [v35.1](#v351)
|
||||||
|
- [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)
|
||||||
|
- [Contributors](#contributors)
|
||||||
- [v34.0](#v340)
|
- [v34.0](#v340)
|
||||||
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
|
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
|
||||||
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
|
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
|
||||||
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
|
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
|
||||||
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
|
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors-1)
|
||||||
- [v33.0](#v330)
|
- [v33.0](#v330)
|
||||||
- [D-Bus based API](#d-bus-based-api)
|
- [D-Bus based API](#d-bus-based-api)
|
||||||
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
|
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||||
- [Contributors](#contributors-1)
|
- [Contributors](#contributors-2)
|
||||||
- [v32.0](#v320)
|
- [v32.0](#v320)
|
||||||
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
||||||
- [API Changes](#api-changes)
|
- [API Changes](#api-changes)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||||
- [Contributors](#contributors-2)
|
- [Contributors](#contributors-3)
|
||||||
- [v31.1](#v311)
|
- [v31.1](#v311)
|
||||||
- [v31.0](#v310)
|
- [v31.0](#v310)
|
||||||
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
||||||
@@ -22,15 +29,15 @@
|
|||||||
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
|
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
|
||||||
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
|
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
|
||||||
- [Documentation Improvements](#documentation-improvements)
|
- [Documentation Improvements](#documentation-improvements)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||||
- [Contributors](#contributors-3)
|
- [Contributors](#contributors-4)
|
||||||
- [v30.0](#v300)
|
- [v30.0](#v300)
|
||||||
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
||||||
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
||||||
- [Heap Profiling Support](#heap-profiling-support)
|
- [Heap Profiling Support](#heap-profiling-support)
|
||||||
- [Documentation Improvements](#documentation-improvements-1)
|
- [Documentation Improvements](#documentation-improvements-1)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||||
- [Contributors](#contributors-4)
|
- [Contributors](#contributors-5)
|
||||||
- [v28.2](#v282)
|
- [v28.2](#v282)
|
||||||
- [v29.0](#v290)
|
- [v29.0](#v290)
|
||||||
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
||||||
@@ -40,10 +47,10 @@
|
|||||||
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
||||||
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
||||||
- [TCP Offload Control](#tcp-offload-control)
|
- [TCP Offload Control](#tcp-offload-control)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||||
- [Removals](#removals)
|
- [Removals](#removals)
|
||||||
- [Deprecations](#deprecations)
|
- [Deprecations](#deprecations)
|
||||||
- [Contributors](#contributors-5)
|
- [Contributors](#contributors-6)
|
||||||
- [v28.1](#v281)
|
- [v28.1](#v281)
|
||||||
- [v28.0](#v280)
|
- [v28.0](#v280)
|
||||||
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
||||||
@@ -51,9 +58,9 @@
|
|||||||
- [Virtualised TPM Support](#virtualised-tpm-support)
|
- [Virtualised TPM Support](#virtualised-tpm-support)
|
||||||
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
||||||
- [README Quick Start Improved](#readme-quick-start-improved)
|
- [README Quick Start Improved](#readme-quick-start-improved)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||||
- [Removals](#removals-1)
|
- [Removals](#removals-1)
|
||||||
- [Contributors](#contributors-6)
|
- [Contributors](#contributors-7)
|
||||||
- [v27.0](#v270)
|
- [v27.0](#v270)
|
||||||
- [Community Engagement](#community-engagement)
|
- [Community Engagement](#community-engagement)
|
||||||
- [Prebuilt Packages](#prebuilt-packages)
|
- [Prebuilt Packages](#prebuilt-packages)
|
||||||
@@ -62,41 +69,41 @@
|
|||||||
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
||||||
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
||||||
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||||
- [Deprecations](#deprecations-1)
|
- [Deprecations](#deprecations-1)
|
||||||
- [Contributors](#contributors-7)
|
- [Contributors](#contributors-8)
|
||||||
- [v26.0](#v260)
|
- [v26.0](#v260)
|
||||||
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
|
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
|
||||||
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||||
- [Deprecations](#deprecations-2)
|
- [Deprecations](#deprecations-2)
|
||||||
- [Removals](#removals-2)
|
- [Removals](#removals-2)
|
||||||
- [Contributors](#contributors-8)
|
- [Contributors](#contributors-9)
|
||||||
- [v25.0](#v250)
|
- [v25.0](#v250)
|
||||||
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
||||||
- [VM "Coredump" Support](#vm-coredump-support)
|
- [VM "Coredump" Support](#vm-coredump-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||||
- [Removals](#removals-3)
|
- [Removals](#removals-3)
|
||||||
- [Contributors](#contributors-9)
|
- [Contributors](#contributors-10)
|
||||||
- [v24.0](#v240)
|
- [v24.0](#v240)
|
||||||
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
||||||
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
||||||
- [Sparse Mmap support](#sparse-mmap-support)
|
- [Sparse Mmap support](#sparse-mmap-support)
|
||||||
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||||
- [Notable Improvements](#notable-improvements)
|
- [Notable Improvements](#notable-improvements)
|
||||||
- [Deprecations](#deprecations-3)
|
- [Deprecations](#deprecations-3)
|
||||||
- [New on the Website](#new-on-the-website)
|
- [New on the Website](#new-on-the-website)
|
||||||
- [Contributors](#contributors-10)
|
- [Contributors](#contributors-11)
|
||||||
- [v23.1](#v231)
|
- [v23.1](#v231)
|
||||||
- [v23.0](#v230)
|
- [v23.0](#v230)
|
||||||
- [vDPA Support](#vdpa-support)
|
- [vDPA Support](#vdpa-support)
|
||||||
- [Updated OS Support list](#updated-os-support-list)
|
- [Updated OS Support list](#updated-os-support-list)
|
||||||
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
||||||
- [`AMX` Support](#amx-support)
|
- [`AMX` Support](#amx-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||||
- [Deprecations](#deprecations-4)
|
- [Deprecations](#deprecations-4)
|
||||||
- [Contributors](#contributors-11)
|
- [Contributors](#contributors-12)
|
||||||
- [v22.1](#v221)
|
- [v22.1](#v221)
|
||||||
- [v22.0](#v220)
|
- [v22.0](#v220)
|
||||||
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
||||||
@@ -107,13 +114,13 @@
|
|||||||
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
||||||
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
||||||
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
- [Notable Bug Fixes](#notable-bug-fixes-13)
|
||||||
- [Contributors](#contributors-12)
|
- [Contributors](#contributors-13)
|
||||||
- [v21.0](#v210)
|
- [v21.0](#v210)
|
||||||
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
|
- [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)
|
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
|
||||||
- [Notable Bug fixes](#notable-bug-fixes-13)
|
- [Notable Bug fixes](#notable-bug-fixes-14)
|
||||||
- [Contributors](#contributors-13)
|
- [Contributors](#contributors-14)
|
||||||
- [v20.2](#v202)
|
- [v20.2](#v202)
|
||||||
- [v20.1](#v201)
|
- [v20.1](#v201)
|
||||||
- [v20.0](#v200)
|
- [v20.0](#v200)
|
||||||
@@ -122,8 +129,8 @@
|
|||||||
- [Improved VFIO support](#improved-vfio-support)
|
- [Improved VFIO support](#improved-vfio-support)
|
||||||
- [Safer code](#safer-code)
|
- [Safer code](#safer-code)
|
||||||
- [Extended documentation](#extended-documentation)
|
- [Extended documentation](#extended-documentation)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-14)
|
- [Notable bug fixes](#notable-bug-fixes-15)
|
||||||
- [Contributors](#contributors-14)
|
- [Contributors](#contributors-15)
|
||||||
- [v19.0](#v190)
|
- [v19.0](#v190)
|
||||||
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
|
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
|
||||||
- [PCI boot time optimisations](#pci-boot-time-optimisations)
|
- [PCI boot time optimisations](#pci-boot-time-optimisations)
|
||||||
@@ -131,8 +138,8 @@
|
|||||||
- [Live migration enhancements](#live-migration-enhancements)
|
- [Live migration enhancements](#live-migration-enhancements)
|
||||||
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
|
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
|
||||||
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
|
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-15)
|
- [Notable bug fixes](#notable-bug-fixes-16)
|
||||||
- [Contributors](#contributors-15)
|
- [Contributors](#contributors-16)
|
||||||
- [v18.0](#v180)
|
- [v18.0](#v180)
|
||||||
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
|
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
|
||||||
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
|
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
|
||||||
@@ -142,23 +149,23 @@
|
|||||||
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
||||||
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
||||||
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-16)
|
- [Notable bug fixes](#notable-bug-fixes-17)
|
||||||
- [Contributors](#contributors-16)
|
- [Contributors](#contributors-17)
|
||||||
- [v17.0](#v170)
|
- [v17.0](#v170)
|
||||||
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
|
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
|
||||||
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
|
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
|
||||||
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
|
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
|
||||||
- [Improved SGX support](#improved-sgx-support)
|
- [Improved SGX support](#improved-sgx-support)
|
||||||
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
|
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-17)
|
- [Notable bug fixes](#notable-bug-fixes-18)
|
||||||
- [Contributors](#contributors-17)
|
- [Contributors](#contributors-18)
|
||||||
- [v16.0](#v160)
|
- [v16.0](#v160)
|
||||||
- [Improved live migration support](#improved-live-migration-support)
|
- [Improved live migration support](#improved-live-migration-support)
|
||||||
- [Improved `vhost-user` support](#improved-vhost-user-support)
|
- [Improved `vhost-user` support](#improved-vhost-user-support)
|
||||||
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
|
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-18)
|
- [Notable bug fixes](#notable-bug-fixes-19)
|
||||||
- [Removed functionality](#removed-functionality)
|
- [Removed functionality](#removed-functionality)
|
||||||
- [Contributors](#contributors-18)
|
- [Contributors](#contributors-19)
|
||||||
- [v15.0](#v150)
|
- [v15.0](#v150)
|
||||||
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
||||||
- [Network device rate limiting](#network-device-rate-limiting)
|
- [Network device rate limiting](#network-device-rate-limiting)
|
||||||
@@ -166,7 +173,7 @@
|
|||||||
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
||||||
- [Bug fixes](#bug-fixes)
|
- [Bug fixes](#bug-fixes)
|
||||||
- [Deprecations](#deprecations-5)
|
- [Deprecations](#deprecations-5)
|
||||||
- [Contributors](#contributors-19)
|
- [Contributors](#contributors-20)
|
||||||
- [v0.14.1](#v0141)
|
- [v0.14.1](#v0141)
|
||||||
- [v0.14.0](#v0140)
|
- [v0.14.0](#v0140)
|
||||||
- [Structured event monitoring](#structured-event-monitoring)
|
- [Structured event monitoring](#structured-event-monitoring)
|
||||||
@@ -176,7 +183,7 @@
|
|||||||
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
||||||
- [Block device rate limiting](#block-device-rate-limiting)
|
- [Block device rate limiting](#block-device-rate-limiting)
|
||||||
- [Deprecations](#deprecations-6)
|
- [Deprecations](#deprecations-6)
|
||||||
- [Contributors](#contributors-20)
|
- [Contributors](#contributors-21)
|
||||||
- [v0.13.0](#v0130)
|
- [v0.13.0](#v0130)
|
||||||
- [Wider VFIO device support](#wider-vfio-device-support)
|
- [Wider VFIO device support](#wider-vfio-device-support)
|
||||||
- [Improved huge page support](#improved-huge-page-support)
|
- [Improved huge page support](#improved-huge-page-support)
|
||||||
@@ -184,13 +191,13 @@
|
|||||||
- [VHD disk image support](#vhd-disk-image-support)
|
- [VHD disk image support](#vhd-disk-image-support)
|
||||||
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
||||||
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
||||||
- [Contributors](#contributors-21)
|
- [Contributors](#contributors-22)
|
||||||
- [v0.12.0](#v0120)
|
- [v0.12.0](#v0120)
|
||||||
- [ARM64 enhancements](#arm64-enhancements)
|
- [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)
|
- [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)
|
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
|
||||||
- [Enhanced "info" API](#enhanced-info-api)
|
- [Enhanced "info" API](#enhanced-info-api)
|
||||||
- [Contributors](#contributors-22)
|
- [Contributors](#contributors-23)
|
||||||
- [v0.11.0](#v0110)
|
- [v0.11.0](#v0110)
|
||||||
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
||||||
- [Windows Guest Support](#windows-guest-support)
|
- [Windows Guest Support](#windows-guest-support)
|
||||||
@@ -202,15 +209,15 @@
|
|||||||
- [Default Log Level Changed](#default-log-level-changed)
|
- [Default Log Level Changed](#default-log-level-changed)
|
||||||
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
||||||
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-19)
|
- [Notable Bug Fixes](#notable-bug-fixes-20)
|
||||||
- [Contributors](#contributors-23)
|
- [Contributors](#contributors-24)
|
||||||
- [v0.10.0](#v0100)
|
- [v0.10.0](#v0100)
|
||||||
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
||||||
- [Memory Zones](#memory-zones)
|
- [Memory Zones](#memory-zones)
|
||||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
||||||
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-20)
|
- [Notable Bug Fixes](#notable-bug-fixes-21)
|
||||||
- [Contributors](#contributors-24)
|
- [Contributors](#contributors-25)
|
||||||
- [v0.9.0](#v090)
|
- [v0.9.0](#v090)
|
||||||
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
||||||
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
||||||
@@ -223,17 +230,17 @@
|
|||||||
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
||||||
- [Intel SGX Support](#intel-sgx-support)
|
- [Intel SGX Support](#intel-sgx-support)
|
||||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-21)
|
- [Notable Bug Fixes](#notable-bug-fixes-22)
|
||||||
- [Contributors](#contributors-25)
|
- [Contributors](#contributors-26)
|
||||||
- [v0.8.0](#v080)
|
- [v0.8.0](#v080)
|
||||||
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
||||||
- [Experimental ARM64 Support](#experimental-arm64-support)
|
- [Experimental ARM64 Support](#experimental-arm64-support)
|
||||||
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
|
- [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)
|
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
|
||||||
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-22)
|
- [Notable Bug Fixes](#notable-bug-fixes-23)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||||
- [Contributors](#contributors-26)
|
- [Contributors](#contributors-27)
|
||||||
- [v0.7.0](#v070)
|
- [v0.7.0](#v070)
|
||||||
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
||||||
- [Alternative `libc` Support](#alternative-libc-support)
|
- [Alternative `libc` Support](#alternative-libc-support)
|
||||||
@@ -243,14 +250,14 @@
|
|||||||
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
||||||
- [Updated Distribution Support](#updated-distribution-support)
|
- [Updated Distribution Support](#updated-distribution-support)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
||||||
- [Contributors](#contributors-27)
|
- [Contributors](#contributors-28)
|
||||||
- [v0.6.0](#v060)
|
- [v0.6.0](#v060)
|
||||||
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
||||||
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
||||||
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
||||||
- [Command Line Interface](#command-line-interface)
|
- [Command Line Interface](#command-line-interface)
|
||||||
- [PVH Boot](#pvh-boot)
|
- [PVH Boot](#pvh-boot)
|
||||||
- [Contributors](#contributors-28)
|
- [Contributors](#contributors-29)
|
||||||
- [v0.5.1](#v051)
|
- [v0.5.1](#v051)
|
||||||
- [v0.5.0](#v050)
|
- [v0.5.0](#v050)
|
||||||
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
||||||
@@ -258,7 +265,7 @@
|
|||||||
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
||||||
- [Development Tools](#development-tools)
|
- [Development Tools](#development-tools)
|
||||||
- [Kata Containers Integration](#kata-containers-integration)
|
- [Kata Containers Integration](#kata-containers-integration)
|
||||||
- [Contributors](#contributors-29)
|
- [Contributors](#contributors-30)
|
||||||
- [v0.4.0](#v040)
|
- [v0.4.0](#v040)
|
||||||
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
||||||
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
||||||
@@ -267,7 +274,7 @@
|
|||||||
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
||||||
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
||||||
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
||||||
- [Contributors](#contributors-30)
|
- [Contributors](#contributors-31)
|
||||||
- [v0.3.0](#v030)
|
- [v0.3.0](#v030)
|
||||||
- [Block device offloading](#block-device-offloading)
|
- [Block device offloading](#block-device-offloading)
|
||||||
- [Network device backend](#network-device-backend)
|
- [Network device backend](#network-device-backend)
|
||||||
@@ -294,6 +301,69 @@
|
|||||||
- [Unit testing](#unit-testing)
|
- [Unit testing](#unit-testing)
|
||||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||||
|
|
||||||
|
# v35.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Fix a deadlock when TDX is enabled (#5845)
|
||||||
|
* Correct default value for vCPU topology on AArch64 (#5893)
|
||||||
|
* 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)
|
||||||
|
|
||||||
|
# v35.0
|
||||||
|
|
||||||
|
This release has been tracked in our [roadmap
|
||||||
|
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||||
|
v35.0. The following user visible changes have been made:
|
||||||
|
|
||||||
|
### `virtio-vsock` Support for Linux Guest Kernel v6.3+
|
||||||
|
|
||||||
|
Since kernel v6.3, a vsock packet can be included in a single descriptor,
|
||||||
|
instead of being split over two descriptors. Our `virtio-vsock` implementation
|
||||||
|
now support both situations.
|
||||||
|
|
||||||
|
### User Specified Serial Number for `virtio-block`
|
||||||
|
|
||||||
|
A new option `serial` is added to the `--block` command that allows users to
|
||||||
|
specify a serial number for block devices which will be guest visible.
|
||||||
|
|
||||||
|
### vCPU TSC Frequency Included in Migration State
|
||||||
|
|
||||||
|
This ensures migration works correctly between hosts that have different TSC
|
||||||
|
frequencies if the guest is running with TSC as the source of timekeeping.
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Disallow concurrent CPU resizing (#5668)
|
||||||
|
* Handle APIC EOI message for MSHV (#5681)
|
||||||
|
* Use wrapping add for memory offset from instruction emulator (#5719)
|
||||||
|
* Add global spell check via the 'typos' GitHub action (#5720)
|
||||||
|
* Ensure probing reads are block size aligned (#5727)
|
||||||
|
* Multiple bug fixes around the latency counter for block devices
|
||||||
|
(#5712, #5750, #5762, #5763)
|
||||||
|
* Replace unsound `static mut` with `once_cell` (#5772)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Christian Blichmann <cblichmann@google.com>
|
||||||
|
* Jianyong Wu <jianyong.wu@arm.com>
|
||||||
|
* Jinank Jain <jinankjain@microsoft.com>
|
||||||
|
* Julian Stecklina <julian.stecklina@cyberus-technology.de>
|
||||||
|
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||||
|
* Philipp Schuster <philipp.schuster@cyberus-technology.de>
|
||||||
|
* Rob Bradford <rbradford@rivosinc.com>
|
||||||
|
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||||
|
* Thomas Barrett <tbarrett@crusoeenergy.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
* Yi Wang <foxywang@tencent.com>
|
||||||
|
* zhongbingnan <zhongbingnan@bytedance.com>
|
||||||
|
|
||||||
# v34.0
|
# v34.0
|
||||||
|
|
||||||
This release has been tracked in our [roadmap
|
This release has been tracked in our [roadmap
|
||||||
@@ -873,7 +943,7 @@ binary with the detection of the hypervisor to use made at runtime.
|
|||||||
### Notable Bug Fixes
|
### Notable Bug Fixes
|
||||||
|
|
||||||
* The prefetchable flag is preserved on BARs for VFIO devices (#4353, #4454)
|
* The prefetchable flag is preserved on BARs for VFIO devices (#4353, #4454)
|
||||||
* PCI Express capabilties for functionality we do not support are now filtered
|
* PCI Express capabilities for functionality we do not support are now filtered
|
||||||
out (#4456)
|
out (#4456)
|
||||||
* GDB breakpoint support is more reliable (#4354, #4363)
|
* GDB breakpoint support is more reliable (#4354, #4363)
|
||||||
* `SIGINT` and `SIGTERM` signals are now handled before the VM has booted
|
* `SIGINT` and `SIGTERM` signals are now handled before the VM has booted
|
||||||
@@ -1228,10 +1298,10 @@ is now 5.15. (#3530)
|
|||||||
|
|
||||||
### Notable Bug fixes
|
### Notable Bug fixes
|
||||||
|
|
||||||
* Multiple fixes were made to the OpenAPI YAML file to match the implementaion (#3555,#3562)
|
* Multiple fixes were made to the OpenAPI YAML file to match the implementation (#3555,#3562)
|
||||||
* Avoid live migration deadlock when triggered during the kernel boot (#3585)
|
* Avoid live migration deadlock when triggered during the kernel boot (#3585)
|
||||||
* Support live migration within firmware (#3586)
|
* Support live migration within firmware (#3586)
|
||||||
* Validate the `virtio-net` desciptor chain (#3548)
|
* Validate the `virtio-net` descriptor chain (#3548)
|
||||||
* `direct=on` (`O_DIRECT`) can now be used with a guest that makes unaligned accesses (e.g. firmware) (#3587)
|
* `direct=on` (`O_DIRECT`) can now be used with a guest that makes unaligned accesses (e.g. firmware) (#3587)
|
||||||
|
|
||||||
### Contributors
|
### Contributors
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# When changing this file don't forget to update the tag name in the
|
# 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
|
# .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 TARGETARCH
|
||||||
ARG RUST_TOOLCHAIN="1.67.1"
|
ARG RUST_TOOLCHAIN="1.67.1"
|
||||||
@@ -43,7 +43,6 @@ RUN apt-get update \
|
|||||||
socat \
|
socat \
|
||||||
dosfstools \
|
dosfstools \
|
||||||
cpio \
|
cpio \
|
||||||
python \
|
|
||||||
python3 \
|
python3 \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
ntfs-3g \
|
ntfs-3g \
|
||||||
@@ -130,17 +129,18 @@ RUN echo 'source $CARGO_HOME/env' >> "$HOME"/.bashrc \
|
|||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
git clone https://github.com/spdk/spdk \
|
git clone https://github.com/spdk/spdk \
|
||||||
&& cd spdk \
|
&& cd spdk \
|
||||||
&& git checkout 6301f8915de32baed10dba1eebed556a6749211a \
|
&& git checkout ef8bcce58f3f02b79c0619a297e4f17e81e62b24 \
|
||||||
&& git submodule update --init \
|
&& git submodule update --init \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& ./scripts/pkgdep.sh \
|
&& ./scripts/pkgdep.sh \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& ./configure --with-vfio-user \
|
&& ./configure --with-vfio-user \
|
||||||
&& make -j $(nproc) TARGET_ARCHITECTURE=skylake \
|
&& make -j $(nproc) TARGET_ARCHITECTURE=skylake \
|
||||||
|
&& rm -rf /usr/local/bin/spdk-nvme \
|
||||||
&& mkdir /usr/local/bin/spdk-nvme \
|
&& mkdir /usr/local/bin/spdk-nvme \
|
||||||
&& cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
&& cp -f ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
||||||
&& cp ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
&& cp -f ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
||||||
&& cp -r ./scripts/rpc /usr/local/bin/spdk-nvme \
|
&& cp -rf ./python /usr/local/bin \
|
||||||
&& cd .. && rm -rf spdk; fi
|
&& cd .. && rm -rf spdk; fi
|
||||||
|
|
||||||
# install swtpm only for x86_64 arch
|
# install swtpm only for x86_64 arch
|
||||||
|
|||||||
0
scripts/check-image-compatability.sh → scripts/check-image-compatibility.sh
Executable file → Normal file
0
scripts/check-image-compatability.sh → scripts/check-image-compatibility.sh
Executable file → Normal file
@@ -1,7 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
export BUILD_TARGET=${BUILD_TARGET-aarch64-unknown-linux-gnu}
|
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
|
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
CLI_NAME="Cloud Hypervisor"
|
CLI_NAME="Cloud Hypervisor"
|
||||||
|
|
||||||
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
|
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
|
||||||
CTR_IMAGE_VERSION="20230804-0"
|
CTR_IMAGE_VERSION="20231220-0"
|
||||||
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
|
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
|
||||||
|
|
||||||
DOCKER_RUNTIME="docker"
|
DOCKER_RUNTIME="docker"
|
||||||
@@ -282,11 +282,10 @@ cmd_build() {
|
|||||||
[ $build = "release" ] && cargo_args+=("--release")
|
[ $build = "release" ] && cargo_args+=("--release")
|
||||||
cargo_args+=(--target "$target")
|
cargo_args+=(--target "$target")
|
||||||
|
|
||||||
rustflags=""
|
rustflags="$RUSTFLAGS"
|
||||||
target_cc=""
|
target_cc=""
|
||||||
if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then
|
if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then
|
||||||
rustflags="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc"
|
||||||
target_cc="musl-gcc"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$DOCKER_RUNTIME run \
|
$DOCKER_RUNTIME run \
|
||||||
@@ -396,6 +395,12 @@ cmd_tests() {
|
|||||||
process_volumes_args
|
process_volumes_args
|
||||||
target="$(uname -m)-unknown-linux-${libc}"
|
target="$(uname -m)-unknown-linux-${libc}"
|
||||||
|
|
||||||
|
rustflags="$RUSTFLAGS"
|
||||||
|
target_cc=""
|
||||||
|
if [ "$(uname -m)" = "aarch64" ] && [ "$libc" = "musl" ]; then
|
||||||
|
rustflags="$rustflags -C link-args=-Wl,-Bstatic -C link-args=-lc"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$unit" = true ]]; then
|
if [[ "$unit" = true ]]; then
|
||||||
say "Running unit tests for $target..."
|
say "Running unit tests for $target..."
|
||||||
$DOCKER_RUNTIME run \
|
$DOCKER_RUNTIME run \
|
||||||
@@ -406,6 +411,8 @@ cmd_tests() {
|
|||||||
--cap-add net_admin \
|
--cap-add net_admin \
|
||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--env BUILD_TARGET="$target" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_unit_tests.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_unit_tests.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -424,7 +431,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -443,7 +452,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -462,7 +473,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -481,7 +494,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -500,7 +515,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -519,7 +536,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
@@ -538,7 +557,9 @@ cmd_tests() {
|
|||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env BUILD_TARGET="$target" \
|
||||||
|
--env RUSTFLAGS="$rustflags" \
|
||||||
|
--env TARGET_CC="$target_cc" \
|
||||||
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \
|
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
|
|||||||
@@ -11,15 +11,16 @@ build_spdk_nvme() {
|
|||||||
SPDK_DIR="$WORKLOADS_DIR/spdk"
|
SPDK_DIR="$WORKLOADS_DIR/spdk"
|
||||||
SPDK_REPO="https://github.com/spdk/spdk.git"
|
SPDK_REPO="https://github.com/spdk/spdk.git"
|
||||||
SPDK_DEPLOY_DIR="/usr/local/bin/spdk-nvme"
|
SPDK_DEPLOY_DIR="/usr/local/bin/spdk-nvme"
|
||||||
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "6301f8915de32baed10dba1eebed556a6749211a"
|
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "ef8bcce58f3f02b79c0619a297e4f17e81e62b24"
|
||||||
|
|
||||||
if [ ! -f "$SPDK_DIR/.built" ]; then
|
if [ ! -f "$SPDK_DIR/.built" ]; then
|
||||||
pushd $SPDK_DIR
|
pushd $SPDK_DIR
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
apt-get update
|
apt-get update
|
||||||
|
sed -i "/grpcio/d" scripts/pkgdep/debian.sh
|
||||||
./scripts/pkgdep.sh
|
./scripts/pkgdep.sh
|
||||||
./configure --with-vfio-user
|
./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
|
make -j `nproc` || exit 1
|
||||||
touch .built
|
touch .built
|
||||||
popd
|
popd
|
||||||
@@ -29,14 +30,15 @@ build_spdk_nvme() {
|
|||||||
fi
|
fi
|
||||||
cp "$WORKLOADS_DIR/spdk/build/bin/nvmf_tgt" $SPDK_DEPLOY_DIR/nvmf_tgt
|
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 "$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/../
|
||||||
}
|
}
|
||||||
|
|
||||||
build_virtiofsd() {
|
build_virtiofsd() {
|
||||||
VIRTIOFSD_DIR="$WORKLOADS_DIR/virtiofsd_build"
|
VIRTIOFSD_DIR="$WORKLOADS_DIR/virtiofsd_build"
|
||||||
VIRTIOFSD_REPO="https://gitlab.com/virtio-fs/virtiofsd.git"
|
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
|
if [ ! -f "$VIRTIOFSD_DIR/.built" ]; then
|
||||||
pushd $VIRTIOFSD_DIR
|
pushd $VIRTIOFSD_DIR
|
||||||
@@ -156,12 +158,25 @@ update_workloads() {
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
# Download Cloud Hypervisor binary from its last stable release
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
LAST_RELEASE_VERSION="v30.0"
|
LAST_RELEASE_VERSION="v34.0"
|
||||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
||||||
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
time wget --quiet $CH_RELEASE_URL -O "$CH_RELEASE_NAME" || exit 1
|
# Repeat a few times to workaround a random wget failure
|
||||||
chmod +x $CH_RELEASE_NAME
|
WGET_RETRY_MAX=10
|
||||||
|
wget_retry=0
|
||||||
|
|
||||||
|
until [ "$wget_retry" -ge "$WGET_RETRY_MAX" ]
|
||||||
|
do
|
||||||
|
time wget $CH_RELEASE_URL -O "$CH_RELEASE_NAME" && break
|
||||||
|
wget_retry=$((wget_retry+1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $wget_retry -ge "$WGET_RETRY_MAX" ]; then
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
chmod +x $CH_RELEASE_NAME
|
||||||
|
fi
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# Build custom kernel for guest VMs
|
# Build custom kernel for guest VMs
|
||||||
@@ -231,12 +246,6 @@ if [ $RES -ne 0 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="aarch64-unknown-linux-${CH_LIBC}"
|
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
|
||||||
export TARGET_CC="musl-gcc"
|
|
||||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
cargo build --all --release --target $BUILD_TARGET
|
cargo build --all --release --target $BUILD_TARGET
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ set -x
|
|||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
export BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|
||||||
@@ -46,7 +44,7 @@ fi
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
# Download Cloud Hypervisor binary from its last stable release
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
LAST_RELEASE_VERSION="v30.0"
|
LAST_RELEASE_VERSION="v34.0"
|
||||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
||||||
CH_RELEASE_NAME="cloud-hypervisor-static"
|
CH_RELEASE_NAME="cloud-hypervisor-static"
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
@@ -60,11 +58,8 @@ if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|||||||
build_custom_linux
|
build_custom_linux
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ set -x
|
|||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
export BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|
||||||
@@ -47,11 +45,8 @@ popd
|
|||||||
|
|
||||||
build_custom_linux
|
build_custom_linux
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -38,11 +38,8 @@ if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -68,12 +68,9 @@ cp $FOCAL_OS_RAW_IMAGE $VFIO_DIR
|
|||||||
cp $FW $VFIO_DIR
|
cp $FW $VFIO_DIR
|
||||||
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --features mshv --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
@@ -89,7 +86,12 @@ echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
|||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test "vfio::test_nvidia" -- --test-threads=1 ${test_binary_args[*]}
|
time cargo test "vfio::test_vfio" -- ${test_binary_args[*]}
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
|
if [ $RES -eq 0 ]; then
|
||||||
|
time cargo test "vfio::test_nvidia" -- --test-threads=1 ${test_binary_args[*]}
|
||||||
|
RES=$?
|
||||||
|
fi
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -20,14 +20,6 @@ WIN_IMAGE_FILE="$WORKLOADS_DIR/$WIN_IMAGE_BASENAME"
|
|||||||
OVMF_FW="$WORKLOADS_DIR/CLOUDHV_EFI.fd"
|
OVMF_FW="$WORKLOADS_DIR/CLOUDHV_EFI.fd"
|
||||||
build_edk2
|
build_edk2
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
|
||||||
export TARGET_CC="musl-gcc"
|
|
||||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if the images are present
|
# Check if the images are present
|
||||||
if [[ ! -f ${WIN_IMAGE_FILE} || ! -f ${OVMF_FW} ]]; then
|
if [[ ! -f ${WIN_IMAGE_FILE} || ! -f ${OVMF_FW} ]]; then
|
||||||
echo "Windows image/firmware not present in the host"
|
echo "Windows image/firmware not present in the host"
|
||||||
|
|||||||
@@ -22,11 +22,8 @@ if [ ! -f "$OVMF_FW" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ set -x
|
|||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
export BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|
||||||
@@ -124,7 +122,7 @@ if [ ! -f "$VIRTIOFSD" ]; then
|
|||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
git clone "https://gitlab.com/virtio-fs/virtiofsd.git" $VIRTIOFSD_DIR
|
git clone "https://gitlab.com/virtio-fs/virtiofsd.git" $VIRTIOFSD_DIR
|
||||||
pushd $VIRTIOFSD_DIR
|
pushd $VIRTIOFSD_DIR
|
||||||
git checkout v1.1.0
|
git checkout v1.8.0
|
||||||
time cargo build --release
|
time cargo build --release
|
||||||
cp target/release/virtiofsd $VIRTIOFSD || exit 1
|
cp target/release/virtiofsd $VIRTIOFSD || exit 1
|
||||||
popd
|
popd
|
||||||
@@ -162,8 +160,6 @@ cp $FOCAL_OS_RAW_IMAGE $VFIO_DIR
|
|||||||
cp $FW $VFIO_DIR
|
cp $FW $VFIO_DIR
|
||||||
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
|
|
||||||
cargo build --features mshv --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
# We always copy a fresh version of our binary for our L2 guest.
|
# We always copy a fresh version of our binary for our L2 guest.
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ source $HOME/.cargo/env
|
|||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
export TEST_ARCH=$(uname -m)
|
export TEST_ARCH=$(uname -m)
|
||||||
export BUILD_TARGET=${BUILD_TARGET-${TEST_ARCH}-unknown-linux-gnu}
|
|
||||||
|
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
@@ -84,11 +82,8 @@ fi
|
|||||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||||
build_custom_linux
|
build_custom_linux
|
||||||
|
|
||||||
BUILD_TARGET="${TEST_ARCH}-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
|
||||||
if [[ "${BUILD_TARGET}" == "${TEST_ARCH}-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "${TEST_ARCH}-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
|
||||||
CFLAGS="-I /usr/include/${TEST_ARCH}-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/${TEST_ARCH}-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ source $(dirname "$0")/test-util.sh
|
|||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
|
|
||||||
BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
|
||||||
cargo_args=("")
|
cargo_args=("")
|
||||||
|
|
||||||
if [[ $hypervisor = "mshv" ]]; then
|
if [[ $hypervisor = "mshv" ]]; then
|
||||||
@@ -14,11 +13,6 @@ elif [[ $(uname -m) = "x86_64" ]]; then
|
|||||||
cargo_args+=("--features tdx")
|
cargo_args+=("--features tdx")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
|
||||||
export TARGET_CC="musl-gcc"
|
|
||||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||||
cargo test --doc --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
cargo test --doc --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ fn rest_api_do_command(toplevel: &TopLevel, socket: &mut UnixStream) -> ApiResul
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dbus_api")]
|
#[cfg(feature = "dbus_api")]
|
||||||
fn dbus_api_do_command(toplevel: &TopLevel, proxy: &mut DBusApi1ProxyBlocking<'_>) -> ApiResult {
|
fn dbus_api_do_command(toplevel: &TopLevel, proxy: &DBusApi1ProxyBlocking<'_>) -> ApiResult {
|
||||||
match toplevel.command {
|
match toplevel.command {
|
||||||
SubCommandEnum::Boot(_) => proxy.api_vm_boot(),
|
SubCommandEnum::Boot(_) => proxy.api_vm_boot(),
|
||||||
SubCommandEnum::Delete(_) => proxy.api_vm_delete(),
|
SubCommandEnum::Delete(_) => proxy.api_vm_delete(),
|
||||||
|
|||||||
97
src/main.rs
97
src/main.rs
@@ -449,18 +449,6 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
|||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "dbus_api")]
|
|
||||||
let dbus_options = match (&toplevel.dbus_name, &toplevel.dbus_path) {
|
|
||||||
(Some(ref name), Some(ref path)) => Ok(Some(DBusApiOptions {
|
|
||||||
service_name: name.to_owned(),
|
|
||||||
object_path: path.to_owned(),
|
|
||||||
system_bus: toplevel.dbus_system_bus,
|
|
||||||
})),
|
|
||||||
(Some(_), None) => Err(Error::MissingDBusObjectPath),
|
|
||||||
(None, Some(_)) => Err(Error::MissingDBusServiceName),
|
|
||||||
(None, None) => Ok(None),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let (api_request_sender, api_request_receiver) = channel();
|
let (api_request_sender, api_request_receiver) = channel();
|
||||||
let api_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateApiEventFd)?;
|
let api_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateApiEventFd)?;
|
||||||
|
|
||||||
@@ -530,31 +518,67 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
|||||||
|
|
||||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
||||||
|
|
||||||
if let Some(ref monitor_config) = toplevel.event_monitor {
|
#[allow(unused_mut)]
|
||||||
let mut parser = OptionParser::new();
|
let mut event_monitor = toplevel
|
||||||
parser.add("path").add("fd");
|
.event_monitor
|
||||||
parser
|
.as_ref()
|
||||||
.parse(monitor_config)
|
.map(|monitor_config| {
|
||||||
.map_err(Error::ParsingEventMonitor)?;
|
let mut parser = OptionParser::new();
|
||||||
|
parser.add("path").add("fd");
|
||||||
|
parser
|
||||||
|
.parse(monitor_config)
|
||||||
|
.map_err(Error::ParsingEventMonitor)?;
|
||||||
|
|
||||||
let file = if parser.is_set("fd") {
|
if parser.is_set("fd") {
|
||||||
let fd = parser
|
let fd = parser
|
||||||
.convert("fd")
|
.convert("fd")
|
||||||
.map_err(Error::ParsingEventMonitor)?
|
.map_err(Error::ParsingEventMonitor)?
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// SAFETY: fd is valid
|
// SAFETY: fd is valid
|
||||||
unsafe { File::from_raw_fd(fd) }
|
Ok(Some(unsafe { File::from_raw_fd(fd) }))
|
||||||
} else if parser.is_set("path") {
|
} else if parser.is_set("path") {
|
||||||
std::fs::OpenOptions::new()
|
Ok(Some(
|
||||||
.write(true)
|
std::fs::OpenOptions::new()
|
||||||
.create(true)
|
.write(true)
|
||||||
.open(parser.get("path").unwrap())
|
.create(true)
|
||||||
.map_err(Error::EventMonitorIo)?
|
.open(parser.get("path").unwrap())
|
||||||
} else {
|
.map_err(Error::EventMonitorIo)?,
|
||||||
return Err(Error::BareEventMonitor);
|
))
|
||||||
};
|
} else {
|
||||||
|
Err(Error::BareEventMonitor)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.map(|event_monitor_file| {
|
||||||
|
event_monitor::set_monitor(event_monitor_file).map_err(Error::EventMonitorIo)
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let monitor = event_monitor::set_monitor(file).map_err(Error::EventMonitorIo)?;
|
#[cfg(feature = "dbus_api")]
|
||||||
|
let dbus_options = match (&toplevel.dbus_name, &toplevel.dbus_path) {
|
||||||
|
(Some(ref name), Some(ref path)) => {
|
||||||
|
// monitor is either set (file based) or not.
|
||||||
|
// if it's not set, create one without file support.
|
||||||
|
let mut monitor = match event_monitor.take() {
|
||||||
|
Some(monitor) => monitor,
|
||||||
|
None => event_monitor::set_monitor(None).map_err(Error::EventMonitorIo)?,
|
||||||
|
};
|
||||||
|
let options = DBusApiOptions {
|
||||||
|
service_name: name.to_owned(),
|
||||||
|
object_path: path.to_owned(),
|
||||||
|
system_bus: toplevel.dbus_system_bus,
|
||||||
|
event_monitor_rx: monitor.subscribe(),
|
||||||
|
};
|
||||||
|
|
||||||
|
event_monitor = Some(monitor);
|
||||||
|
Ok(Some(options))
|
||||||
|
}
|
||||||
|
(Some(_), None) => Err(Error::MissingDBusObjectPath),
|
||||||
|
(None, Some(_)) => Err(Error::MissingDBusServiceName),
|
||||||
|
(None, None) => Ok(None),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
if let Some(monitor) = event_monitor {
|
||||||
vmm::start_event_monitor_thread(
|
vmm::start_event_monitor_thread(
|
||||||
monitor,
|
monitor,
|
||||||
&seccomp_action,
|
&seccomp_action,
|
||||||
@@ -638,6 +662,9 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(all(feature = "tdx", feature = "sev_snp"))]
|
||||||
|
compile_error!("Feature 'tdx' and 'sev_snp' are mutually exclusive.");
|
||||||
|
|
||||||
#[cfg(feature = "dhat-heap")]
|
#[cfg(feature = "dhat-heap")]
|
||||||
let _profiler = dhat::Profiler::new_heap();
|
let _profiler = dhat::Profiler::new_heap();
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ write_files:
|
|||||||
# 1G ram requires 512 pages
|
# 1G ram requires 512 pages
|
||||||
echo 512 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 512 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210609-0.raw path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:05.0/ path=/sys/bus/pci/devices/0000:00:07.0/ path=/sys/bus/pci/devices/0000:00:08.0/ --api-socket /tmp/ch_api.sock
|
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210609-0.raw --disk path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:05.0/ --device path=/sys/bus/pci/devices/0000:00:07.0/ --device path=/sys/bus/pci/devices/0000:00:08.0/ --api-socket /tmp/ch_api.sock
|
||||||
|
|
||||||
-
|
-
|
||||||
path: /etc/systemd/system/notify-booted.service
|
path: /etc/systemd/system/notify-booted.service
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
dirs = "5.0.0"
|
dirs = "5.0.0"
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
|
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ impl GuestNetworkConfig {
|
|||||||
None => DEFAULT_TCP_LISTENER_TIMEOUT,
|
None => DEFAULT_TCP_LISTENER_TIMEOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
match (|| -> Result<(), WaitForBootError> {
|
let mut closure = || -> Result<(), WaitForBootError> {
|
||||||
let listener =
|
let listener =
|
||||||
TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
|
TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
|
||||||
listener
|
listener
|
||||||
@@ -143,7 +143,9 @@ impl GuestNetworkConfig {
|
|||||||
Err(WaitForBootError::Accept(e))
|
Err(WaitForBootError::Accept(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})() {
|
};
|
||||||
|
|
||||||
|
match closure() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -559,7 +561,7 @@ fn scp_to_guest_with_auth(
|
|||||||
) -> Result<(), SshCommandError> {
|
) -> Result<(), SshCommandError> {
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
loop {
|
loop {
|
||||||
match (|| -> Result<(), SshCommandError> {
|
let closure = || -> Result<(), SshCommandError> {
|
||||||
let tcp =
|
let tcp =
|
||||||
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
|
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
|
||||||
let mut sess = Session::new().unwrap();
|
let mut sess = Session::new().unwrap();
|
||||||
@@ -592,7 +594,9 @@ fn scp_to_guest_with_auth(
|
|||||||
let _ = channel.wait_close();
|
let _ = channel.wait_close();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})() {
|
};
|
||||||
|
|
||||||
|
match closure() {
|
||||||
Ok(_) => break,
|
Ok(_) => break,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
@@ -647,7 +651,7 @@ pub fn ssh_command_ip_with_auth(
|
|||||||
|
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
loop {
|
loop {
|
||||||
match (|| -> Result<(), SshCommandError> {
|
let mut closure = || -> Result<(), SshCommandError> {
|
||||||
let tcp =
|
let tcp =
|
||||||
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
|
TcpStream::connect(format!("{ip}:22")).map_err(SshCommandError::Connection)?;
|
||||||
let mut sess = Session::new().unwrap();
|
let mut sess = Session::new().unwrap();
|
||||||
@@ -676,7 +680,9 @@ pub fn ssh_command_ip_with_auth(
|
|||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
})() {
|
};
|
||||||
|
|
||||||
|
match closure() {
|
||||||
Ok(_) => break,
|
Ok(_) => break,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
|
|||||||
@@ -888,7 +888,7 @@ fn check_sequential_events_exact(expected_events: &[&MetaEvent], event_file: &st
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if events from the input 'expected_events' are matched exactly
|
// Return true if events from the input 'latest_events' are matched exactly
|
||||||
// with the most recent events from the 'event_file'
|
// with the most recent events from the 'event_file'
|
||||||
fn check_latest_events_exact(latest_events: &[&MetaEvent], event_file: &str) -> bool {
|
fn check_latest_events_exact(latest_events: &[&MetaEvent], event_file: &str) -> bool {
|
||||||
let json_events = parse_event_file(event_file);
|
let json_events = parse_event_file(event_file);
|
||||||
@@ -1844,7 +1844,7 @@ fn test_memory_mergeable(mergeable: bool) {
|
|||||||
"mergeable=off"
|
"mergeable=off"
|
||||||
};
|
};
|
||||||
|
|
||||||
// We are assuming the rest of the system in our CI is not using mergeable memeory
|
// We are assuming the rest of the system in our CI is not using mergeable memory
|
||||||
let ksm_ps_init = get_ksm_pages_shared();
|
let ksm_ps_init = get_ksm_pages_shared();
|
||||||
assert!(ksm_ps_init == 0);
|
assert!(ksm_ps_init == 0);
|
||||||
|
|
||||||
@@ -3297,16 +3297,19 @@ mod common_parallel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
fn test_vhost_user_blk_default() {
|
fn test_vhost_user_blk_default() {
|
||||||
test_vhost_user_blk(2, false, false, Some(&prepare_vubd))
|
test_vhost_user_blk(2, false, false, Some(&prepare_vubd))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
fn test_vhost_user_blk_readonly() {
|
fn test_vhost_user_blk_readonly() {
|
||||||
test_vhost_user_blk(1, true, false, Some(&prepare_vubd))
|
test_vhost_user_blk(1, true, false, Some(&prepare_vubd))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
fn test_vhost_user_blk_direct() {
|
fn test_vhost_user_blk_direct() {
|
||||||
test_vhost_user_blk(1, false, true, Some(&prepare_vubd))
|
test_vhost_user_blk(1, false, true, Some(&prepare_vubd))
|
||||||
}
|
}
|
||||||
@@ -3823,7 +3826,7 @@ mod common_parallel {
|
|||||||
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
||||||
let guest = Guest::new(Box::new(focal));
|
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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
let console_str: &str = "console=ttyS0";
|
let console_str: &str = "console=ttyS0";
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@@ -4022,7 +4025,7 @@ mod common_parallel {
|
|||||||
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
||||||
let guest = Guest::new(Box::new(focal));
|
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)
|
let mut child = GuestCommand::new(&guest)
|
||||||
.args(["--cpus", "boot=1"])
|
.args(["--cpus", "boot=1"])
|
||||||
.args(["--memory", "size=512M"])
|
.args(["--memory", "size=512M"])
|
||||||
@@ -4070,7 +4073,6 @@ mod common_parallel {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[cfg(not(feature = "mshv"))]
|
#[cfg(not(feature = "mshv"))]
|
||||||
#[ignore = "See #4324"]
|
|
||||||
// The VFIO integration test starts cloud-hypervisor guest with 3 TAP
|
// The VFIO integration test starts cloud-hypervisor guest with 3 TAP
|
||||||
// backed networking interfaces, bound through a simple bridge on the host.
|
// backed networking interfaces, bound through a simple bridge on the host.
|
||||||
// So if the nested cloud-hypervisor succeeds in getting a directly
|
// So if the nested cloud-hypervisor succeeds in getting a directly
|
||||||
@@ -4084,8 +4086,8 @@ mod common_parallel {
|
|||||||
fn test_vfio() {
|
fn test_vfio() {
|
||||||
setup_vfio_network_interfaces();
|
setup_vfio_network_interfaces();
|
||||||
|
|
||||||
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
let jammy = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
|
||||||
let guest = Guest::new_from_ip_range(Box::new(focal), "172.18", 0);
|
let guest = Guest::new_from_ip_range(Box::new(jammy), "172.18", 0);
|
||||||
|
|
||||||
let mut workload_path = dirs::home_dir().unwrap();
|
let mut workload_path = dirs::home_dir().unwrap();
|
||||||
workload_path.push("workloads");
|
workload_path.push("workloads");
|
||||||
@@ -4848,12 +4850,13 @@ mod common_parallel {
|
|||||||
.args(["--memory", format!("size={guest_memory_size_kb}K").as_str()])
|
.args(["--memory", format!("size={guest_memory_size_kb}K").as_str()])
|
||||||
.args(["--kernel", kernel_path.to_str().unwrap()])
|
.args(["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||||
|
.default_net()
|
||||||
.default_disks()
|
.default_disks()
|
||||||
.capture_output()
|
.capture_output()
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
thread::sleep(std::time::Duration::new(20, 0));
|
guest.wait_vm_boot(None).unwrap();
|
||||||
|
|
||||||
let r = std::panic::catch_unwind(|| {
|
let r = std::panic::catch_unwind(|| {
|
||||||
let overhead = get_vmm_overhead(child.id(), guest_memory_size_kb);
|
let overhead = get_vmm_overhead(child.id(), guest_memory_size_kb);
|
||||||
@@ -6175,7 +6178,7 @@ mod common_parallel {
|
|||||||
guest.ssh_command("screen -dmS reboot sh -c \"sleep 5; echo s | tee /proc/sysrq-trigger; echo c | sudo tee /proc/sysrq-trigger\"").unwrap();
|
guest.ssh_command("screen -dmS reboot sh -c \"sleep 5; echo s | tee /proc/sysrq-trigger; echo c | sudo tee /proc/sysrq-trigger\"").unwrap();
|
||||||
// Allow some time for the watchdog to trigger (max 30s) and reboot to happen
|
// Allow some time for the watchdog to trigger (max 30s) and reboot to happen
|
||||||
guest.wait_vm_boot(Some(50)).unwrap();
|
guest.wait_vm_boot(Some(50)).unwrap();
|
||||||
// Check a reboot is triggerred by the watchdog
|
// Check a reboot is triggered by the watchdog
|
||||||
expected_reboot_count += 1;
|
expected_reboot_count += 1;
|
||||||
assert_eq!(get_reboot_count(&guest), expected_reboot_count);
|
assert_eq!(get_reboot_count(&guest), expected_reboot_count);
|
||||||
|
|
||||||
@@ -6853,6 +6856,7 @@ mod common_parallel {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[ignore = "See #5756"]
|
||||||
fn test_vdpa_net() {
|
fn test_vdpa_net() {
|
||||||
// Before trying to run the test, verify the vdpa_sim_net module is correctly loaded.
|
// Before trying to run the test, verify the vdpa_sim_net module is correctly loaded.
|
||||||
if !exec_host_command_status("lsmod | grep vdpa_sim_net").success() {
|
if !exec_host_command_status("lsmod | grep vdpa_sim_net").success() {
|
||||||
@@ -7809,6 +7813,7 @@ mod windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore = "See #6037"]
|
||||||
#[cfg(not(feature = "mshv"))]
|
#[cfg(not(feature = "mshv"))]
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
fn test_windows_guest_disk_hotplug() {
|
fn test_windows_guest_disk_hotplug() {
|
||||||
@@ -7904,6 +7909,7 @@ mod windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore = "See #6037"]
|
||||||
#[cfg(not(feature = "mshv"))]
|
#[cfg(not(feature = "mshv"))]
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
#[cfg(not(target_arch = "aarch64"))]
|
||||||
fn test_windows_guest_disk_hotplug_multi() {
|
fn test_windows_guest_disk_hotplug_multi() {
|
||||||
@@ -8787,13 +8793,13 @@ mod live_migration {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and report any errors occured during the live-migration
|
// Check and report any errors occurred during the live-migration
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
print_and_panic(
|
print_and_panic(
|
||||||
src_child,
|
src_child,
|
||||||
dest_child,
|
dest_child,
|
||||||
None,
|
None,
|
||||||
"Error occured during live-migration",
|
"Error occurred during live-migration",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8961,13 +8967,13 @@ mod live_migration {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and report any errors occured during the live-migration
|
// Check and report any errors occurred during the live-migration
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
print_and_panic(
|
print_and_panic(
|
||||||
src_child,
|
src_child,
|
||||||
dest_child,
|
dest_child,
|
||||||
None,
|
None,
|
||||||
"Error occured during live-migration",
|
"Error occurred during live-migration",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9187,13 +9193,13 @@ mod live_migration {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and report any errors occured during the live-migration
|
// Check and report any errors occurred during the live-migration
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
print_and_panic(
|
print_and_panic(
|
||||||
src_child,
|
src_child,
|
||||||
dest_child,
|
dest_child,
|
||||||
None,
|
None,
|
||||||
"Error occured during live-migration",
|
"Error occurred during live-migration",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9406,13 +9412,13 @@ mod live_migration {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and report any errors occured during the live-migration
|
// Check and report any errors occurred during the live-migration
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
print_and_panic(
|
print_and_panic(
|
||||||
src_child,
|
src_child,
|
||||||
dest_child,
|
dest_child,
|
||||||
None,
|
None,
|
||||||
"Error occured during live-migration",
|
"Error occurred during live-migration",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9447,7 +9453,7 @@ mod live_migration {
|
|||||||
guest.ssh_command("screen -dmS reboot sh -c \"sleep 5; echo s | tee /proc/sysrq-trigger; echo c | sudo tee /proc/sysrq-trigger\"").unwrap();
|
guest.ssh_command("screen -dmS reboot sh -c \"sleep 5; echo s | tee /proc/sysrq-trigger; echo c | sudo tee /proc/sysrq-trigger\"").unwrap();
|
||||||
// Allow some time for the watchdog to trigger (max 30s) and reboot to happen
|
// Allow some time for the watchdog to trigger (max 30s) and reboot to happen
|
||||||
guest.wait_vm_boot(Some(50)).unwrap();
|
guest.wait_vm_boot(Some(50)).unwrap();
|
||||||
// Check a reboot is triggerred by the watchdog
|
// Check a reboot is triggered by the watchdog
|
||||||
expected_reboot_count += 1;
|
expected_reboot_count += 1;
|
||||||
assert_eq!(get_reboot_count(&guest), expected_reboot_count);
|
assert_eq!(get_reboot_count(&guest), expected_reboot_count);
|
||||||
|
|
||||||
@@ -9516,13 +9522,13 @@ mod live_migration {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check and report any errors occured during the live-migration
|
// Check and report any errors occurred during the live-migration
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
print_and_panic(
|
print_and_panic(
|
||||||
src_child,
|
src_child,
|
||||||
dest_child,
|
dest_child,
|
||||||
Some(ovs_child),
|
Some(ovs_child),
|
||||||
"Error occured during live-migration",
|
"Error occurred during live-migration",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9667,6 +9673,7 @@ mod live_migration {
|
|||||||
|
|
||||||
// Require to run ovs-dpdk tests sequentially because they rely on the same ovs-dpdk setup
|
// Require to run ovs-dpdk tests sequentially because they rely on the same ovs-dpdk setup
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore = "See #5532"]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[cfg(not(feature = "mshv"))]
|
#[cfg(not(feature = "mshv"))]
|
||||||
fn test_live_migration_ovs_dpdk() {
|
fn test_live_migration_ovs_dpdk() {
|
||||||
@@ -9681,6 +9688,7 @@ mod live_migration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore = "See #5532"]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[cfg(not(feature = "mshv"))]
|
#[cfg(not(feature = "mshv"))]
|
||||||
fn test_live_upgrade_ovs_dpdk() {
|
fn test_live_upgrade_ovs_dpdk() {
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ impl Ptm for PtmCap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GET_TPMESTABLISHED Reponse */
|
/* GET_TPMESTABLISHED Response */
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PtmEstResp {
|
pub struct PtmEstResp {
|
||||||
pub bit: u8,
|
pub bit: u8,
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ authors = ["The Cloud Hypervisor Authors"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
tracing = []
|
tracing = []
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ impl Tracer {
|
|||||||
if let Some(depth) = self.thread_depths.get_mut(thread_name) {
|
if let Some(depth) = self.thread_depths.get_mut(thread_name) {
|
||||||
depth.fetch_sub(1, Ordering::SeqCst);
|
depth.fetch_sub(1, Ordering::SeqCst);
|
||||||
} else {
|
} else {
|
||||||
panic!("Unmatched decreas for thread: {thread_name}");
|
panic!("Unmatched decrease for thread: {thread_name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ argh = "0.1.9"
|
|||||||
block = { path = "../block" }
|
block = { path = "../block" }
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
option_parser = { path = "../option_parser" }
|
option_parser = { path = "../option_parser" }
|
||||||
vhost = { version = "0.7.0", features = ["vhost-user-slave"] }
|
vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
|
||||||
vhost-user-backend = "0.9.0"
|
vhost-user-backend = "0.10.1"
|
||||||
virtio-bindings = "0.2.0"
|
virtio-bindings = "0.2.0"
|
||||||
virtio-queue = "0.8.0"
|
virtio-queue = "0.9.0"
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// SPDX-License-Identifier: (Apache-2.0 AND BSD-3-Clause)
|
// SPDX-License-Identifier: (Apache-2.0 AND BSD-3-Clause)
|
||||||
|
|
||||||
use block::{
|
use block::{
|
||||||
build_disk_image_id,
|
build_serial,
|
||||||
qcow::{self, ImageType, QcowFile},
|
qcow::{self, ImageType, QcowFile},
|
||||||
Request, VirtioBlockConfig,
|
Request, VirtioBlockConfig,
|
||||||
};
|
};
|
||||||
@@ -90,7 +90,7 @@ impl convert::From<Error> for io::Error {
|
|||||||
|
|
||||||
struct VhostUserBlkThread {
|
struct VhostUserBlkThread {
|
||||||
disk_image: Arc<Mutex<dyn DiskFile>>,
|
disk_image: Arc<Mutex<dyn DiskFile>>,
|
||||||
disk_image_id: Vec<u8>,
|
serial: Vec<u8>,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
event_idx: bool,
|
event_idx: bool,
|
||||||
kill_evt: EventFd,
|
kill_evt: EventFd,
|
||||||
@@ -101,14 +101,14 @@ struct VhostUserBlkThread {
|
|||||||
impl VhostUserBlkThread {
|
impl VhostUserBlkThread {
|
||||||
fn new(
|
fn new(
|
||||||
disk_image: Arc<Mutex<dyn DiskFile>>,
|
disk_image: Arc<Mutex<dyn DiskFile>>,
|
||||||
disk_image_id: Vec<u8>,
|
serial: Vec<u8>,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
writeback: Arc<AtomicBool>,
|
writeback: Arc<AtomicBool>,
|
||||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Ok(VhostUserBlkThread {
|
Ok(VhostUserBlkThread {
|
||||||
disk_image,
|
disk_image,
|
||||||
disk_image_id,
|
serial,
|
||||||
disk_nsectors,
|
disk_nsectors,
|
||||||
event_idx: false,
|
event_idx: false,
|
||||||
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
|
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
|
||||||
@@ -137,7 +137,7 @@ impl VhostUserBlkThread {
|
|||||||
&mut self.disk_image.lock().unwrap().deref_mut(),
|
&mut self.disk_image.lock().unwrap().deref_mut(),
|
||||||
self.disk_nsectors,
|
self.disk_nsectors,
|
||||||
desc_chain.memory(),
|
desc_chain.memory(),
|
||||||
&self.disk_image_id,
|
&self.serial,
|
||||||
) {
|
) {
|
||||||
Ok(l) => {
|
Ok(l) => {
|
||||||
len = l;
|
len = l;
|
||||||
@@ -222,7 +222,7 @@ impl VhostUserBlkBackend {
|
|||||||
let image: File = options.open(&image_path).unwrap();
|
let image: File = options.open(&image_path).unwrap();
|
||||||
let mut raw_img: qcow::RawFile = qcow::RawFile::new(image, direct);
|
let mut raw_img: qcow::RawFile = qcow::RawFile::new(image, direct);
|
||||||
|
|
||||||
let image_id = build_disk_image_id(&PathBuf::from(&image_path));
|
let serial = build_serial(&PathBuf::from(&image_path));
|
||||||
let image_type = qcow::detect_image_type(&mut raw_img).unwrap();
|
let image_type = qcow::detect_image_type(&mut raw_img).unwrap();
|
||||||
let image = match image_type {
|
let image = match image_type {
|
||||||
ImageType::Raw => Arc::new(Mutex::new(raw_img)) as Arc<Mutex<dyn DiskFile>>,
|
ImageType::Raw => Arc::new(Mutex::new(raw_img)) as Arc<Mutex<dyn DiskFile>>,
|
||||||
@@ -250,7 +250,7 @@ impl VhostUserBlkBackend {
|
|||||||
for i in 0..num_queues {
|
for i in 0..num_queues {
|
||||||
let thread = Mutex::new(VhostUserBlkThread::new(
|
let thread = Mutex::new(VhostUserBlkThread::new(
|
||||||
image.clone(),
|
image.clone(),
|
||||||
image_id.clone(),
|
serial.clone(),
|
||||||
nsectors,
|
nsectors,
|
||||||
writeback.clone(),
|
writeback.clone(),
|
||||||
mem.clone(),
|
mem.clone(),
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ build = "../build.rs"
|
|||||||
argh = "0.1.9"
|
argh = "0.1.9"
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
net_util = { path = "../net_util" }
|
net_util = { path = "../net_util" }
|
||||||
option_parser = { path = "../option_parser" }
|
option_parser = { path = "../option_parser" }
|
||||||
vhost = { version = "0.7.0", features = ["vhost-user-slave"] }
|
vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
|
||||||
vhost-user-backend = "0.9.0"
|
vhost-user-backend = "0.10.1"
|
||||||
virtio-bindings = "0.2.0"
|
virtio-bindings = "0.2.0"
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
|
|||||||
@@ -8,31 +8,31 @@ edition = "2021"
|
|||||||
default = []
|
default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
arc-swap = "1.5.1"
|
arc-swap = "1.5.1"
|
||||||
block = { path = "../block" }
|
block = { path = "../block" }
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
epoll = "4.3.3"
|
epoll = "4.3.3"
|
||||||
event_monitor = { path = "../event_monitor" }
|
event_monitor = { path = "../event_monitor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
net_gen = { path = "../net_gen" }
|
net_gen = { path = "../net_gen" }
|
||||||
net_util = { path = "../net_util" }
|
net_util = { path = "../net_util" }
|
||||||
pci = { path = "../pci" }
|
pci = { path = "../pci" }
|
||||||
rate_limiter = { path = "../rate_limiter" }
|
rate_limiter = { path = "../rate_limiter" }
|
||||||
seccompiler = "0.3.0"
|
seccompiler = "0.3.0"
|
||||||
serde = { version = "1.0.164", features = ["derive"] }
|
serde = { version = "1.0.168", features = ["derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.107"
|
||||||
serial_buffer = { path = "../serial_buffer" }
|
serial_buffer = { path = "../serial_buffer" }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
versionize = "0.1.10"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vhost = { version = "0.7.0", features = ["vhost-user-master", "vhost-user-slave", "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-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||||
virtio-queue = "0.8.0"
|
virtio-queue = "0.9.0"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { version = "0.11.0", 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-migration = { path = "../vm-migration" }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ use thiserror::Error;
|
|||||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
use virtio_queue::{Queue, QueueT};
|
use virtio_queue::{Queue, QueueT};
|
||||||
|
use vm_allocator::page_size::{align_page_size_down, get_page_size};
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
||||||
GuestMemoryError, GuestMemoryRegion,
|
GuestMemoryError, GuestMemoryRegion,
|
||||||
@@ -94,6 +95,50 @@ pub struct VirtioBalloonConfig {
|
|||||||
actual: u32,
|
actual: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct PartiallyBalloonedPage {
|
||||||
|
addr: u64,
|
||||||
|
bitmap: Vec<u64>,
|
||||||
|
page_size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartiallyBalloonedPage {
|
||||||
|
fn new() -> Self {
|
||||||
|
let page_size = get_page_size();
|
||||||
|
let len = ((page_size >> VIRTIO_BALLOON_PFN_SHIFT) + 63) / 64;
|
||||||
|
// Initial each padding bit as 1 in bitmap.
|
||||||
|
let mut bitmap = vec![0_u64; len as usize];
|
||||||
|
let pad_num = len * 64 - (page_size >> VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
bitmap[(len - 1) as usize] = !((1 << (64 - pad_num)) - 1);
|
||||||
|
Self {
|
||||||
|
addr: 0,
|
||||||
|
bitmap,
|
||||||
|
page_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pfn_match(&self, addr: u64) -> bool {
|
||||||
|
self.addr == addr & !(self.page_size - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bitmap_full(&self) -> bool {
|
||||||
|
self.bitmap.iter().all(|b| *b == u64::MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bit(&mut self, addr: u64) {
|
||||||
|
let addr_offset = (addr % self.page_size) >> VIRTIO_BALLOON_PFN_SHIFT;
|
||||||
|
self.bitmap[(addr_offset / 64) as usize] |= 1 << (addr_offset % 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
let len = ((self.page_size >> VIRTIO_BALLOON_PFN_SHIFT) + 63) / 64;
|
||||||
|
self.addr = 0;
|
||||||
|
self.bitmap = vec![0; len as usize];
|
||||||
|
let pad_num = len * 64 - (self.page_size >> VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
self.bitmap[(len - 1) as usize] = !((1 << (64 - pad_num)) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const CONFIG_ACTUAL_OFFSET: u64 = 4;
|
const CONFIG_ACTUAL_OFFSET: u64 = 4;
|
||||||
const CONFIG_ACTUAL_SIZE: usize = 4;
|
const CONFIG_ACTUAL_SIZE: usize = 4;
|
||||||
|
|
||||||
@@ -109,6 +154,7 @@ struct BalloonEpollHandler {
|
|||||||
reporting_queue_evt: Option<EventFd>,
|
reporting_queue_evt: Option<EventFd>,
|
||||||
kill_evt: EventFd,
|
kill_evt: EventFd,
|
||||||
pause_evt: EventFd,
|
pause_evt: EventFd,
|
||||||
|
pbp: Option<PartiallyBalloonedPage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BalloonEpollHandler {
|
impl BalloonEpollHandler {
|
||||||
@@ -165,6 +211,43 @@ impl BalloonEpollHandler {
|
|||||||
Self::advise_memory_range(memory, range_base, range_len, libc::MADV_DONTNEED)
|
Self::advise_memory_range(memory, range_base, range_len, libc::MADV_DONTNEED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn release_memory_range_4k(
|
||||||
|
pbp: &mut Option<PartiallyBalloonedPage>,
|
||||||
|
memory: &GuestMemoryMmap,
|
||||||
|
pfn: u32,
|
||||||
|
) -> result::Result<(), Error> {
|
||||||
|
let range_base = GuestAddress((pfn as u64) << VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
let range_len = 1 << VIRTIO_BALLOON_PFN_SHIFT;
|
||||||
|
|
||||||
|
let page_size: u64 = get_page_size();
|
||||||
|
if page_size == 1 << VIRTIO_BALLOON_PFN_SHIFT {
|
||||||
|
return Self::release_memory_range(memory, range_base, range_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if pbp.is_none() {
|
||||||
|
*pbp = Some(PartiallyBalloonedPage::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !pbp.as_ref().unwrap().pfn_match(range_base.0) {
|
||||||
|
// We are trying to free memory region in a different pfn with current pbp. Flush pbp.
|
||||||
|
pbp.as_mut().unwrap().reset();
|
||||||
|
pbp.as_mut().unwrap().addr = align_page_size_down(range_base.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pbp.as_mut().unwrap().set_bit(range_base.0);
|
||||||
|
if pbp.as_ref().unwrap().bitmap_full() {
|
||||||
|
Self::release_memory_range(
|
||||||
|
memory,
|
||||||
|
vm_memory::GuestAddress(pbp.as_ref().unwrap().addr),
|
||||||
|
page_size as usize,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
pbp.as_mut().unwrap().reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> {
|
fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> {
|
||||||
let mut used_descs = false;
|
let mut used_descs = false;
|
||||||
while let Some(mut desc_chain) =
|
while let Some(mut desc_chain) =
|
||||||
@@ -193,18 +276,18 @@ impl BalloonEpollHandler {
|
|||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
offset += data_chunk_size as u64;
|
offset += data_chunk_size as u64;
|
||||||
|
|
||||||
let range_base = GuestAddress((pfn as u64) << VIRTIO_BALLOON_PFN_SHIFT);
|
|
||||||
let range_len = 1 << VIRTIO_BALLOON_PFN_SHIFT;
|
|
||||||
|
|
||||||
match queue_index {
|
match queue_index {
|
||||||
0 => {
|
0 => {
|
||||||
Self::release_memory_range(desc_chain.memory(), range_base, range_len)?;
|
Self::release_memory_range_4k(&mut self.pbp, desc_chain.memory(), pfn)?;
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
|
let page_size = get_page_size() as usize;
|
||||||
|
let rbase = align_page_size_down((pfn as u64) << VIRTIO_BALLOON_PFN_SHIFT);
|
||||||
|
|
||||||
Self::advise_memory_range(
|
Self::advise_memory_range(
|
||||||
desc_chain.memory(),
|
desc_chain.memory(),
|
||||||
range_base,
|
vm_memory::GuestAddress(rbase),
|
||||||
range_len,
|
page_size,
|
||||||
libc::MADV_WILLNEED,
|
libc::MADV_WILLNEED,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@@ -543,6 +626,7 @@ impl VirtioDevice for Balloon {
|
|||||||
reporting_queue_evt,
|
reporting_queue_evt,
|
||||||
kill_evt,
|
kill_evt,
|
||||||
pause_evt,
|
pause_evt,
|
||||||
|
pbp: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use crate::GuestMemoryMmap;
|
|||||||
use crate::VirtioInterrupt;
|
use crate::VirtioInterrupt;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use block::{
|
use block::{
|
||||||
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_disk_image_id, Request,
|
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_serial, Request,
|
||||||
RequestType, VirtioBlockConfig,
|
RequestType, VirtioBlockConfig,
|
||||||
};
|
};
|
||||||
use rate_limiter::{RateLimiter, TokenType};
|
use rate_limiter::{RateLimiter, TokenType};
|
||||||
@@ -106,13 +106,13 @@ impl Default for BlockCounters {
|
|||||||
read_bytes: Arc::new(AtomicU64::new(0)),
|
read_bytes: Arc::new(AtomicU64::new(0)),
|
||||||
read_ops: Arc::new(AtomicU64::new(0)),
|
read_ops: Arc::new(AtomicU64::new(0)),
|
||||||
read_latency_min: Arc::new(AtomicU64::new(u64::MAX)),
|
read_latency_min: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
read_latency_max: Arc::new(AtomicU64::new(0)),
|
read_latency_max: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
read_latency_avg: Arc::new(AtomicU64::new(0)),
|
read_latency_avg: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
write_bytes: Arc::new(AtomicU64::new(0)),
|
write_bytes: Arc::new(AtomicU64::new(0)),
|
||||||
write_ops: Arc::new(AtomicU64::new(0)),
|
write_ops: Arc::new(AtomicU64::new(0)),
|
||||||
write_latency_min: Arc::new(AtomicU64::new(u64::MAX)),
|
write_latency_min: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
write_latency_max: Arc::new(AtomicU64::new(0)),
|
write_latency_max: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
write_latency_avg: Arc::new(AtomicU64::new(0)),
|
write_latency_avg: Arc::new(AtomicU64::new(u64::MAX)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ struct BlockEpollHandler {
|
|||||||
disk_image: Box<dyn AsyncIo>,
|
disk_image: Box<dyn AsyncIo>,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||||
disk_image_id: Vec<u8>,
|
serial: Vec<u8>,
|
||||||
kill_evt: EventFd,
|
kill_evt: EventFd,
|
||||||
pause_evt: EventFd,
|
pause_evt: EventFd,
|
||||||
writeback: Arc<AtomicBool>,
|
writeback: Arc<AtomicBool>,
|
||||||
@@ -205,7 +205,7 @@ impl BlockEpollHandler {
|
|||||||
desc_chain.memory(),
|
desc_chain.memory(),
|
||||||
self.disk_nsectors,
|
self.disk_nsectors,
|
||||||
self.disk_image.as_mut(),
|
self.disk_image.as_mut(),
|
||||||
&self.disk_image_id,
|
&self.serial,
|
||||||
desc_chain.head_index() as u64,
|
desc_chain.head_index() as u64,
|
||||||
)
|
)
|
||||||
.map_err(Error::RequestExecuting)?
|
.map_err(Error::RequestExecuting)?
|
||||||
@@ -281,10 +281,12 @@ impl BlockEpollHandler {
|
|||||||
request.complete_async().map_err(Error::RequestCompleting)?;
|
request.complete_async().map_err(Error::RequestCompleting)?;
|
||||||
|
|
||||||
let latency = request.start.elapsed().as_micros() as u64;
|
let latency = request.start.elapsed().as_micros() as u64;
|
||||||
let read_ops_last = self.counters.read_ops.load(Ordering::Relaxed) as i64;
|
let read_ops_last = self.counters.read_ops.load(Ordering::Relaxed);
|
||||||
let write_ops_last = self.counters.write_ops.load(Ordering::Relaxed) as i64;
|
let write_ops_last = self.counters.write_ops.load(Ordering::Relaxed);
|
||||||
let mut read_avg = self.counters.read_latency_avg.load(Ordering::Relaxed) as i64;
|
let read_max = self.counters.read_latency_max.load(Ordering::Relaxed);
|
||||||
let mut write_avg = self.counters.write_latency_avg.load(Ordering::Relaxed) as i64;
|
let write_max = self.counters.write_latency_max.load(Ordering::Relaxed);
|
||||||
|
let mut read_avg = self.counters.read_latency_avg.load(Ordering::Relaxed);
|
||||||
|
let mut write_avg = self.counters.write_latency_avg.load(Ordering::Relaxed);
|
||||||
let (status, len) = if result >= 0 {
|
let (status, len) = if result >= 0 {
|
||||||
match request.request_type {
|
match request.request_type {
|
||||||
RequestType::In => {
|
RequestType::In => {
|
||||||
@@ -297,14 +299,24 @@ impl BlockEpollHandler {
|
|||||||
.read_latency_min
|
.read_latency_min
|
||||||
.store(latency, Ordering::Relaxed);
|
.store(latency, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
if latency > self.counters.read_latency_max.load(Ordering::Relaxed) {
|
if latency > read_max || read_max == u64::MAX {
|
||||||
self.counters
|
self.counters
|
||||||
.read_latency_max
|
.read_latency_max
|
||||||
.store(latency, Ordering::Relaxed);
|
.store(latency, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
read_avg = read_avg
|
|
||||||
+ ((latency * LATENCY_SCALE) as i64 - read_avg)
|
// Special case the first real latency report
|
||||||
/ (read_ops_last + read_ops.0 as i64);
|
read_avg = if read_avg == u64::MAX {
|
||||||
|
latency * LATENCY_SCALE
|
||||||
|
} else {
|
||||||
|
// Cumulative average is guaranteed to be
|
||||||
|
// positive if being calculated properly
|
||||||
|
(read_avg as i64
|
||||||
|
+ ((latency * LATENCY_SCALE) as i64 - read_avg as i64)
|
||||||
|
/ (read_ops_last + read_ops.0) as i64)
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
RequestType::Out => {
|
RequestType::Out => {
|
||||||
if !request.writeback {
|
if !request.writeback {
|
||||||
@@ -319,25 +331,35 @@ impl BlockEpollHandler {
|
|||||||
.write_latency_min
|
.write_latency_min
|
||||||
.store(latency, Ordering::Relaxed);
|
.store(latency, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
if latency > self.counters.write_latency_max.load(Ordering::Relaxed) {
|
if latency > write_max || write_max == u64::MAX {
|
||||||
self.counters
|
self.counters
|
||||||
.write_latency_max
|
.write_latency_max
|
||||||
.store(latency, Ordering::Relaxed);
|
.store(latency, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
write_avg = write_avg
|
|
||||||
+ ((latency * LATENCY_SCALE) as i64 - write_avg)
|
// Special case the first real latency report
|
||||||
/ (write_ops_last + write_ops.0 as i64);
|
write_avg = if write_avg == u64::MAX {
|
||||||
|
latency * LATENCY_SCALE
|
||||||
|
} else {
|
||||||
|
// Cumulative average is guaranteed to be
|
||||||
|
// positive if being calculated properly
|
||||||
|
(write_avg as i64
|
||||||
|
+ ((latency * LATENCY_SCALE) as i64 - write_avg as i64)
|
||||||
|
/ (write_ops_last + write_ops.0) as i64)
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.counters
|
self.counters
|
||||||
.read_latency_avg
|
.read_latency_avg
|
||||||
.store(read_avg as u64, Ordering::Relaxed);
|
.store(read_avg, Ordering::Relaxed);
|
||||||
|
|
||||||
self.counters
|
self.counters
|
||||||
.write_latency_avg
|
.write_latency_avg
|
||||||
.store(write_avg as u64, Ordering::Relaxed);
|
.store(write_avg, Ordering::Relaxed);
|
||||||
|
|
||||||
(VIRTIO_BLK_S_OK, result as u32)
|
(VIRTIO_BLK_S_OK, result as u32)
|
||||||
} else {
|
} else {
|
||||||
@@ -488,6 +510,7 @@ pub struct Block {
|
|||||||
rate_limiter_config: Option<RateLimiterConfig>,
|
rate_limiter_config: Option<RateLimiterConfig>,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
read_only: bool,
|
read_only: bool,
|
||||||
|
serial: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Versionize)]
|
#[derive(Versionize)]
|
||||||
@@ -512,6 +535,7 @@ impl Block {
|
|||||||
iommu: bool,
|
iommu: bool,
|
||||||
num_queues: usize,
|
num_queues: usize,
|
||||||
queue_size: u16,
|
queue_size: u16,
|
||||||
|
serial: Option<String>,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
rate_limiter_config: Option<RateLimiterConfig>,
|
rate_limiter_config: Option<RateLimiterConfig>,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
@@ -592,6 +616,8 @@ impl Block {
|
|||||||
(disk_nsectors, avail_features, 0, config, false)
|
(disk_nsectors, avail_features, 0, config, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let serial = serial.map(Vec::from).unwrap_or(build_serial(&disk_path));
|
||||||
|
|
||||||
Ok(Block {
|
Ok(Block {
|
||||||
common: VirtioCommon {
|
common: VirtioCommon {
|
||||||
device_type: VirtioDeviceType::Block as u32,
|
device_type: VirtioDeviceType::Block as u32,
|
||||||
@@ -614,6 +640,7 @@ impl Block {
|
|||||||
rate_limiter_config,
|
rate_limiter_config,
|
||||||
exit_evt,
|
exit_evt,
|
||||||
read_only,
|
read_only,
|
||||||
|
serial,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +737,6 @@ impl VirtioDevice for Block {
|
|||||||
) -> ActivateResult {
|
) -> ActivateResult {
|
||||||
self.common.activate(&queues, &interrupt_cb)?;
|
self.common.activate(&queues, &interrupt_cb)?;
|
||||||
|
|
||||||
let disk_image_id = build_disk_image_id(&self.disk_path);
|
|
||||||
self.update_writeback();
|
self.update_writeback();
|
||||||
|
|
||||||
let mut epoll_threads = Vec::new();
|
let mut epoll_threads = Vec::new();
|
||||||
@@ -738,7 +764,7 @@ impl VirtioDevice for Block {
|
|||||||
})?,
|
})?,
|
||||||
disk_nsectors: self.disk_nsectors,
|
disk_nsectors: self.disk_nsectors,
|
||||||
interrupt_cb: interrupt_cb.clone(),
|
interrupt_cb: interrupt_cb.clone(),
|
||||||
disk_image_id: disk_image_id.clone(),
|
serial: self.serial.clone(),
|
||||||
kill_evt,
|
kill_evt,
|
||||||
pause_evt,
|
pause_evt,
|
||||||
writeback: self.writeback.clone(),
|
writeback: self.writeback.clone(),
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ impl VirtioPciCommonConfig {
|
|||||||
&mut self,
|
&mut self,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
data: &mut [u8],
|
data: &mut [u8],
|
||||||
queues: &mut [Queue],
|
queues: &[Queue],
|
||||||
device: Arc<Mutex<dyn VirtioDevice>>,
|
device: Arc<Mutex<dyn VirtioDevice>>,
|
||||||
) {
|
) {
|
||||||
assert!(data.len() <= 8);
|
assert!(data.len() <= 8);
|
||||||
@@ -385,35 +385,35 @@ mod tests {
|
|||||||
// Can set all bits of driver_status.
|
// Can set all bits of driver_status.
|
||||||
regs.write(0x14, &[0x55], &mut queues, dev.clone());
|
regs.write(0x14, &[0x55], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0x00];
|
let mut read_back = vec![0x00];
|
||||||
regs.read(0x14, &mut read_back, &mut queues, dev.clone());
|
regs.read(0x14, &mut read_back, &queues, dev.clone());
|
||||||
assert_eq!(read_back[0], 0x55);
|
assert_eq!(read_back[0], 0x55);
|
||||||
|
|
||||||
// The config generation register is read only.
|
// The config generation register is read only.
|
||||||
regs.write(0x15, &[0xaa], &mut queues, dev.clone());
|
regs.write(0x15, &[0xaa], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0x00];
|
let mut read_back = vec![0x00];
|
||||||
regs.read(0x15, &mut read_back, &mut queues, dev.clone());
|
regs.read(0x15, &mut read_back, &queues, dev.clone());
|
||||||
assert_eq!(read_back[0], 0x55);
|
assert_eq!(read_back[0], 0x55);
|
||||||
|
|
||||||
// Device features is read-only and passed through from the device.
|
// Device features is read-only and passed through from the device.
|
||||||
regs.write(0x04, &[0, 0, 0, 0], &mut queues, dev.clone());
|
regs.write(0x04, &[0, 0, 0, 0], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0, 0, 0, 0];
|
let mut read_back = vec![0, 0, 0, 0];
|
||||||
regs.read(0x04, &mut read_back, &mut queues, dev.clone());
|
regs.read(0x04, &mut read_back, &queues, dev.clone());
|
||||||
assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES as u32);
|
assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES as u32);
|
||||||
|
|
||||||
// Feature select registers are read/write.
|
// Feature select registers are read/write.
|
||||||
regs.write(0x00, &[1, 2, 3, 4], &mut queues, dev.clone());
|
regs.write(0x00, &[1, 2, 3, 4], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0, 0, 0, 0];
|
let mut read_back = vec![0, 0, 0, 0];
|
||||||
regs.read(0x00, &mut read_back, &mut queues, dev.clone());
|
regs.read(0x00, &mut read_back, &queues, dev.clone());
|
||||||
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
||||||
regs.write(0x08, &[1, 2, 3, 4], &mut queues, dev.clone());
|
regs.write(0x08, &[1, 2, 3, 4], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0, 0, 0, 0];
|
let mut read_back = vec![0, 0, 0, 0];
|
||||||
regs.read(0x08, &mut read_back, &mut queues, dev.clone());
|
regs.read(0x08, &mut read_back, &queues, dev.clone());
|
||||||
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
||||||
|
|
||||||
// 'queue_select' can be read and written.
|
// 'queue_select' can be read and written.
|
||||||
regs.write(0x16, &[0xaa, 0x55], &mut queues, dev.clone());
|
regs.write(0x16, &[0xaa, 0x55], &mut queues, dev.clone());
|
||||||
let mut read_back = vec![0x00, 0x00];
|
let mut read_back = vec![0x00, 0x00];
|
||||||
regs.read(0x16, &mut read_back, &mut queues, dev);
|
regs.read(0x16, &mut read_back, &queues, dev);
|
||||||
assert_eq!(read_back[0], 0xaa);
|
assert_eq!(read_back[0], 0xaa);
|
||||||
assert_eq!(read_back[1], 0x55);
|
assert_eq!(read_back[1], 0x55);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1116,7 +1116,7 @@ impl PciDevice for VirtioPciDevice {
|
|||||||
o if o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => self.common_config.read(
|
o if o < COMMON_CONFIG_BAR_OFFSET + COMMON_CONFIG_SIZE => self.common_config.read(
|
||||||
o - COMMON_CONFIG_BAR_OFFSET,
|
o - COMMON_CONFIG_BAR_OFFSET,
|
||||||
data,
|
data,
|
||||||
&mut self.queues,
|
&self.queues,
|
||||||
self.device.clone(),
|
self.device.clone(),
|
||||||
),
|
),
|
||||||
o if (ISR_CONFIG_BAR_OFFSET..ISR_CONFIG_BAR_OFFSET + ISR_CONFIG_SIZE).contains(&o) => {
|
o if (ISR_CONFIG_BAR_OFFSET..ISR_CONFIG_BAR_OFFSET + ISR_CONFIG_SIZE).contains(&o) => {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ pub enum Error {
|
|||||||
VhostUserSetLogBase(VhostError),
|
VhostUserSetLogBase(VhostError),
|
||||||
#[error("Invalid used address")]
|
#[error("Invalid used address")]
|
||||||
UsedAddress,
|
UsedAddress,
|
||||||
#[error("Invalid features provided from vhost-user backe")]
|
#[error("Invalid features provided from vhost-user backend")]
|
||||||
InvalidFeatures,
|
InvalidFeatures,
|
||||||
#[error("Missing file descriptor for the region")]
|
#[error("Missing file descriptor for the region")]
|
||||||
MissingRegionFd,
|
MissingRegionFd,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
get_host_address_range, GuestMemoryMmap, GuestRegionMmap, MmapRegion, VirtioInterrupt,
|
get_host_address_range, GuestMemoryMmap, GuestRegionMmap, MmapRegion, VirtioInterrupt,
|
||||||
VirtioInterruptType,
|
VirtioInterruptType,
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::ffi;
|
use std::ffi;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||||
@@ -201,7 +201,7 @@ impl VhostUserHandle {
|
|||||||
|
|
||||||
let mut vrings_info = Vec::new();
|
let mut vrings_info = Vec::new();
|
||||||
for (queue_index, queue, queue_evt) in queues.iter() {
|
for (queue_index, queue, queue_evt) in queues.iter() {
|
||||||
let actual_size: usize = queue.size().try_into().unwrap();
|
let actual_size: usize = queue.size().into();
|
||||||
|
|
||||||
let config_data = VringConfigData {
|
let config_data = VringConfigData {
|
||||||
queue_max_size: queue.max_size(),
|
queue_max_size: queue.max_size(),
|
||||||
|
|||||||
@@ -213,9 +213,7 @@ mod tests {
|
|||||||
fn test_push_wrap() {
|
fn test_push_wrap() {
|
||||||
let mut txbuf = TxBuf::new();
|
let mut txbuf = TxBuf::new();
|
||||||
let mut sink = TestSink::new();
|
let mut sink = TestSink::new();
|
||||||
let mut tmp: Vec<u8> = Vec::new();
|
let tmp: Vec<u8> = vec![0; TxBuf::SIZE - 2];
|
||||||
|
|
||||||
tmp.resize(TxBuf::SIZE - 2, 0);
|
|
||||||
txbuf.push(tmp.as_slice()).unwrap();
|
txbuf.push(tmp.as_slice()).unwrap();
|
||||||
txbuf.flush_to(&mut sink).unwrap();
|
txbuf.flush_to(&mut sink).unwrap();
|
||||||
sink.clear();
|
sink.clear();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use super::defs;
|
|||||||
use super::{Result, VsockError};
|
use super::{Result, VsockError};
|
||||||
use crate::get_host_address_range;
|
use crate::get_host_address_range;
|
||||||
use virtio_queue::DescriptorChain;
|
use virtio_queue::DescriptorChain;
|
||||||
use vm_memory::GuestMemory;
|
use vm_memory::{Address, GuestMemory};
|
||||||
use vm_virtio::{AccessPlatform, Translatable};
|
use vm_virtio::{AccessPlatform, Translatable};
|
||||||
|
|
||||||
// The vsock packet header is defined by the C struct:
|
// The vsock packet header is defined by the C struct:
|
||||||
@@ -133,7 +133,7 @@ impl VsockPacket {
|
|||||||
hdr: get_host_address_range(
|
hdr: get_host_address_range(
|
||||||
desc_chain.memory(),
|
desc_chain.memory(),
|
||||||
head.addr()
|
head.addr()
|
||||||
.translate_gva(access_platform, head.len() as usize),
|
.translate_gva(access_platform, VSOCK_PKT_HDR_SIZE),
|
||||||
VSOCK_PKT_HDR_SIZE,
|
VSOCK_PKT_HDR_SIZE,
|
||||||
)
|
)
|
||||||
.ok_or(VsockError::GuestMemory)?,
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
@@ -152,32 +152,46 @@ impl VsockPacket {
|
|||||||
return Err(VsockError::InvalidPktLen(pkt.len()));
|
return Err(VsockError::InvalidPktLen(pkt.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the packet header showed a non-zero length, there should be a data descriptor here.
|
// Prior to Linux v6.3 there are two descriptors
|
||||||
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
if head.has_next() {
|
||||||
|
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
||||||
|
|
||||||
// TX data should be read-only.
|
// TX data should be read-only.
|
||||||
if buf_desc.is_write_only() {
|
if buf_desc.is_write_only() {
|
||||||
return Err(VsockError::UnreadableDescriptor);
|
return Err(VsockError::UnreadableDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The data buffer should be large enough to fit the size of the data, as described by
|
||||||
|
// the header descriptor.
|
||||||
|
if buf_desc.len() < pkt.len() {
|
||||||
|
return Err(VsockError::BufDescTooSmall);
|
||||||
|
}
|
||||||
|
let buf_size = buf_desc.len() as usize;
|
||||||
|
pkt.buf_size = buf_size;
|
||||||
|
pkt.buf = Some(
|
||||||
|
get_host_address_range(
|
||||||
|
desc_chain.memory(),
|
||||||
|
buf_desc.addr().translate_gva(access_platform, buf_size),
|
||||||
|
pkt.buf_size,
|
||||||
|
)
|
||||||
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let buf_size: usize = head.len() as usize - VSOCK_PKT_HDR_SIZE;
|
||||||
|
pkt.buf_size = buf_size;
|
||||||
|
pkt.buf = Some(
|
||||||
|
get_host_address_range(
|
||||||
|
desc_chain.memory(),
|
||||||
|
head.addr()
|
||||||
|
.checked_add(VSOCK_PKT_HDR_SIZE as u64)
|
||||||
|
.unwrap()
|
||||||
|
.translate_gva(access_platform, buf_size),
|
||||||
|
buf_size,
|
||||||
|
)
|
||||||
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The data buffer should be large enough to fit the size of the data, as described by
|
|
||||||
// the header descriptor.
|
|
||||||
if buf_desc.len() < pkt.len() {
|
|
||||||
return Err(VsockError::BufDescTooSmall);
|
|
||||||
}
|
|
||||||
|
|
||||||
pkt.buf_size = buf_desc.len() as usize;
|
|
||||||
pkt.buf = Some(
|
|
||||||
get_host_address_range(
|
|
||||||
desc_chain.memory(),
|
|
||||||
buf_desc
|
|
||||||
.addr()
|
|
||||||
.translate_gva(access_platform, buf_desc.len() as usize),
|
|
||||||
pkt.buf_size,
|
|
||||||
)
|
|
||||||
.ok_or(VsockError::GuestMemory)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(pkt)
|
Ok(pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,33 +221,53 @@ impl VsockPacket {
|
|||||||
return Err(VsockError::HdrDescTooSmall(head.len()));
|
return Err(VsockError::HdrDescTooSmall(head.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// All RX descriptor chains should have a header and a data descriptor.
|
// Prior to Linux v6.3 there are two descriptors
|
||||||
if !head.has_next() {
|
if head.has_next() {
|
||||||
return Err(VsockError::BufDescMissing);
|
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
||||||
}
|
let buf_size = buf_desc.len() as usize;
|
||||||
let buf_desc = desc_chain.next().ok_or(VsockError::BufDescMissing)?;
|
|
||||||
let buf_size = buf_desc.len() as usize;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
hdr: get_host_address_range(
|
hdr: get_host_address_range(
|
||||||
desc_chain.memory(),
|
|
||||||
head.addr()
|
|
||||||
.translate_gva(access_platform, head.len() as usize),
|
|
||||||
VSOCK_PKT_HDR_SIZE,
|
|
||||||
)
|
|
||||||
.ok_or(VsockError::GuestMemory)?,
|
|
||||||
buf: Some(
|
|
||||||
get_host_address_range(
|
|
||||||
desc_chain.memory(),
|
desc_chain.memory(),
|
||||||
buf_desc
|
head.addr()
|
||||||
.addr()
|
.translate_gva(access_platform, VSOCK_PKT_HDR_SIZE),
|
||||||
.translate_gva(access_platform, buf_desc.len() as usize),
|
VSOCK_PKT_HDR_SIZE,
|
||||||
buf_size,
|
|
||||||
)
|
)
|
||||||
.ok_or(VsockError::GuestMemory)?,
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
),
|
buf: Some(
|
||||||
buf_size,
|
get_host_address_range(
|
||||||
})
|
desc_chain.memory(),
|
||||||
|
buf_desc.addr().translate_gva(access_platform, buf_size),
|
||||||
|
buf_size,
|
||||||
|
)
|
||||||
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
|
),
|
||||||
|
buf_size,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let buf_size: usize = head.len() as usize - VSOCK_PKT_HDR_SIZE;
|
||||||
|
Ok(Self {
|
||||||
|
hdr: get_host_address_range(
|
||||||
|
desc_chain.memory(),
|
||||||
|
head.addr()
|
||||||
|
.translate_gva(access_platform, VSOCK_PKT_HDR_SIZE),
|
||||||
|
VSOCK_PKT_HDR_SIZE,
|
||||||
|
)
|
||||||
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
|
buf: Some(
|
||||||
|
get_host_address_range(
|
||||||
|
desc_chain.memory(),
|
||||||
|
head.addr()
|
||||||
|
.checked_add(VSOCK_PKT_HDR_SIZE as u64)
|
||||||
|
.unwrap()
|
||||||
|
.translate_gva(access_platform, buf_size),
|
||||||
|
buf_size,
|
||||||
|
)
|
||||||
|
.ok_or(VsockError::GuestMemory)?,
|
||||||
|
),
|
||||||
|
buf_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides in-place, byte-slice, access to the vsock packet header.
|
/// Provides in-place, byte-slice, access to the vsock packet header.
|
||||||
@@ -503,16 +537,6 @@ mod tests {
|
|||||||
expect_asm_error!(tx, test_ctx, handler_ctx, VsockError::InvalidPktLen(_));
|
expect_asm_error!(tx, test_ctx, handler_ctx, VsockError::InvalidPktLen(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test case:
|
|
||||||
// - packet header advertises some data length; and
|
|
||||||
// - the data descriptor is missing.
|
|
||||||
{
|
|
||||||
create_context!(test_ctx, handler_ctx);
|
|
||||||
set_pkt_len(1024, &handler_ctx.guest_txvq.dtable[0], &test_ctx.mem);
|
|
||||||
handler_ctx.guest_txvq.dtable[0].flags.set(0);
|
|
||||||
expect_asm_error!(tx, test_ctx, handler_ctx, VsockError::BufDescMissing);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test case: error on write-only buf descriptor.
|
// Test case: error on write-only buf descriptor.
|
||||||
{
|
{
|
||||||
create_context!(test_ctx, handler_ctx);
|
create_context!(test_ctx, handler_ctx);
|
||||||
@@ -568,15 +592,6 @@ mod tests {
|
|||||||
.set(VSOCK_PKT_HDR_SIZE as u32 - 1);
|
.set(VSOCK_PKT_HDR_SIZE as u32 - 1);
|
||||||
expect_asm_error!(rx, test_ctx, handler_ctx, VsockError::HdrDescTooSmall(_));
|
expect_asm_error!(rx, test_ctx, handler_ctx, VsockError::HdrDescTooSmall(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test case: RX descriptor chain is missing the packet buffer descriptor.
|
|
||||||
{
|
|
||||||
create_context!(test_ctx, handler_ctx);
|
|
||||||
handler_ctx.guest_rxvq.dtable[0]
|
|
||||||
.flags
|
|
||||||
.set(VRING_DESC_F_WRITE.try_into().unwrap());
|
|
||||||
expect_asm_error!(rx, test_ctx, handler_ctx, VsockError::BufDescMissing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ authors = ["The Chromium OS Authors"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.139"
|
libc = "0.2.147"
|
||||||
vm-memory = "0.11.0"
|
vm-memory = "0.12.2"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
mod address;
|
mod address;
|
||||||
mod gsi;
|
mod gsi;
|
||||||
/// page size related utility funtions
|
/// page size related utility functions
|
||||||
pub mod page_size;
|
pub mod page_size;
|
||||||
mod system;
|
mod system;
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub struct SystemAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SystemAllocator {
|
impl SystemAllocator {
|
||||||
/// Creates a new `SystemAllocator` for managing addresses and irq numvers.
|
/// Creates a new `SystemAllocator` for managing addresses and irq numbers.
|
||||||
/// Can return `None` if `base` + `size` overflows a u64
|
/// Can return `None` if `base` + `size` overflows a u64
|
||||||
///
|
///
|
||||||
/// * `io_base` - (X86) The starting address of IO memory.
|
/// * `io_base` - (X86) The starting address of IO memory.
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ kvm = ["vfio-ioctls/kvm"]
|
|||||||
mshv = ["vfio-ioctls/mshv"]
|
mshv = ["vfio-ioctls/mshv"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.75"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||||
vm-memory = { version = "0.11.0", features = ["backend-mmap"] }
|
vm-memory = { version = "0.12.2", features = ["backend-mmap"] }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ impl Ord for BusRange {
|
|||||||
|
|
||||||
impl PartialOrd for BusRange {
|
impl PartialOrd for BusRange {
|
||||||
fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
|
||||||
self.base.partial_cmp(&other.base)
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user