mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
407 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebaea6fe0f | ||
|
|
0150de55d2 | ||
|
|
75e3a3d982 | ||
|
|
3b10699743 | ||
|
|
d0798aad59 | ||
|
|
e52175c2ab | ||
|
|
ffd1411e7c | ||
|
|
a14ebbb758 | ||
|
|
02358d3091 | ||
|
|
025447e8cc | ||
|
|
d582121143 | ||
|
|
38b8e387ea | ||
|
|
3538afc1fe | ||
|
|
d96614fe42 | ||
|
|
7076684124 | ||
|
|
fa07d83565 | ||
|
|
80f6dda932 | ||
|
|
f160572f9d | ||
|
|
9626288d4f | ||
|
|
e2f9c4e756 | ||
|
|
e674577ea9 | ||
|
|
49db713124 | ||
|
|
f0aa70c78b | ||
|
|
db3bd6bb16 | ||
|
|
5e7a77e5f9 | ||
|
|
ea753b4f32 | ||
|
|
5587245bf2 | ||
|
|
bc5f70d1ed | ||
|
|
0e16ffbcff | ||
|
|
3a0429c998 | ||
|
|
7f29cef5d2 | ||
|
|
4a32f17aad | ||
|
|
0c452ac895 | ||
|
|
32353fa389 | ||
|
|
33e2a7121e | ||
|
|
2eb984b45d | ||
|
|
3bcd3e7f4c | ||
|
|
58966e952d | ||
|
|
f809f44c02 | ||
|
|
c0cc5cb01d | ||
|
|
da4fdeb017 | ||
|
|
f5f63130bf | ||
|
|
cb8075e53b | ||
|
|
30c5aeff23 | ||
|
|
86d09f6caa | ||
|
|
7db7410920 | ||
|
|
64c76693c4 | ||
|
|
c622b43f85 | ||
|
|
1651253777 | ||
|
|
3824f17516 | ||
|
|
8ab3aaee6a | ||
|
|
12f11b5619 | ||
|
|
16a9882153 | ||
|
|
2caf5e3b2b | ||
|
|
218be2642e | ||
|
|
cd0df05808 | ||
|
|
4ff0686d37 | ||
|
|
288cea917e | ||
|
|
d3f66f8702 | ||
|
|
8e1ba99e8d | ||
|
|
3ffc105f83 | ||
|
|
b1bd87df19 | ||
|
|
3f9e8d676a | ||
|
|
fe82322727 | ||
|
|
e89e5c9beb | ||
|
|
e85ac2695f | ||
|
|
c2c813599d | ||
|
|
3c0817a1b7 | ||
|
|
387d56879b | ||
|
|
f24f35b65d | ||
|
|
28926c7454 | ||
|
|
24543e7076 | ||
|
|
21474e280d | ||
|
|
5f722d0d3f | ||
|
|
06f57abdf9 | ||
|
|
42c19e14c5 | ||
|
|
058a61148c | ||
|
|
425902b296 | ||
|
|
54f39aa8cb | ||
|
|
1108bd1967 | ||
|
|
707cea2182 | ||
|
|
c47e3b8689 | ||
|
|
5bd7a1f03c | ||
|
|
c614dcb9f7 | ||
|
|
7fe399598d | ||
|
|
25a38b25c4 | ||
|
|
b9fb849b83 | ||
|
|
0c00da1dd8 | ||
|
|
28fb2d3235 | ||
|
|
bf39146caa | ||
|
|
1dfe4eda5c | ||
|
|
5530795898 | ||
|
|
db06ef78ba | ||
|
|
95c6ee3e6a | ||
|
|
d4168056be | ||
|
|
592a65f52e | ||
|
|
6e101f479c | ||
|
|
6d4862245d | ||
|
|
78abbfa604 | ||
|
|
664c9e3eb3 | ||
|
|
1f71c28656 | ||
|
|
30e06eaaba | ||
|
|
0ed196820e | ||
|
|
bde2370b18 | ||
|
|
960a9e0ff7 | ||
|
|
3277c27e0d | ||
|
|
dea10b5500 | ||
|
|
691d9b16db | ||
|
|
400a351bb0 | ||
|
|
fa9fb26952 | ||
|
|
938b0bfcec | ||
|
|
a5a2e591c9 | ||
|
|
677c8831af | ||
|
|
634c53ea50 | ||
|
|
657660e5c2 | ||
|
|
b60e6f7cb1 | ||
|
|
4a7c858fdc | ||
|
|
85a72efed7 | ||
|
|
8afdcb98d4 | ||
|
|
6c36c60330 | ||
|
|
6239b8ad7a | ||
|
|
4fed2d4ed7 | ||
|
|
ec0c1b01c4 | ||
|
|
f77ea5a2ce | ||
|
|
f17aa3755f | ||
|
|
744a049007 | ||
|
|
e70bd069b3 | ||
|
|
bfeb3120f5 | ||
|
|
ce6d88d187 | ||
|
|
56fe4c61af | ||
|
|
1d1a087fc5 | ||
|
|
f1276c58d2 | ||
|
|
da33eb5e8c | ||
|
|
fdeb4f7c46 | ||
|
|
7388f71228 | ||
|
|
eebf4f10e3 | ||
|
|
3d1b2eb4e5 | ||
|
|
16740b4fcd | ||
|
|
e97fe7a43e | ||
|
|
87eed369cd | ||
|
|
79f4c2db01 | ||
|
|
6df8f0bbf3 | ||
|
|
bbd0667b98 | ||
|
|
b40633f92c | ||
|
|
2f47bea809 | ||
|
|
f38360deb6 | ||
|
|
fc8facddee | ||
|
|
bf9f79081a | ||
|
|
ec1679406e | ||
|
|
17107c59ac | ||
|
|
62f17ccf8c | ||
|
|
cb03540ffd | ||
|
|
0270d697ab | ||
|
|
47529796d0 | ||
|
|
1c786610b7 | ||
|
|
4a99d3dbaf | ||
|
|
e6aa792c01 | ||
|
|
eb6daa2fc3 | ||
|
|
f767e97fa5 | ||
|
|
f076819d81 | ||
|
|
3c8e280bf1 | ||
|
|
c1ecfd23be | ||
|
|
80de77a6e6 | ||
|
|
adb3dcdc13 | ||
|
|
e972eb7c74 | ||
|
|
203dfdc156 | ||
|
|
6ccf037972 | ||
|
|
4a04d1f8f2 | ||
|
|
c274ce4d49 | ||
|
|
047432a81b | ||
|
|
8358d100cc | ||
|
|
82aa0e1222 | ||
|
|
edca82c4bd | ||
|
|
7e9c61ab18 | ||
|
|
f81220ae2d | ||
|
|
4ca066f077 | ||
|
|
88ed85247e | ||
|
|
de1af55e22 | ||
|
|
bf059914a6 | ||
|
|
3952cc6629 | ||
|
|
e15cac55aa | ||
|
|
824c0c962d | ||
|
|
37521ddff7 | ||
|
|
11e9f43305 | ||
|
|
89218b6d1e | ||
|
|
da95c0d784 | ||
|
|
1795afadb8 | ||
|
|
a87d1bbaa1 | ||
|
|
babece08c6 | ||
|
|
5a9779f88c | ||
|
|
45d3db48cf | ||
|
|
f03258bb2a | ||
|
|
5264d545dd | ||
|
|
6175cc0977 | ||
|
|
0c34846ef6 | ||
|
|
4f172ae4b6 | ||
|
|
0f12fe9b3b | ||
|
|
6e084572d4 | ||
|
|
0c9c56f5a6 | ||
|
|
cd2b167b33 | ||
|
|
a63d526423 | ||
|
|
735457f0e1 | ||
|
|
719c9b8233 | ||
|
|
4338486c6f | ||
|
|
a784d9a649 | ||
|
|
ee3f9ef334 | ||
|
|
f8201bc151 | ||
|
|
b212f2823d | ||
|
|
6bf6d95c55 | ||
|
|
e591385a67 | ||
|
|
ed87e42e6f | ||
|
|
6a099257e8 | ||
|
|
85c068f769 | ||
|
|
65716f1376 | ||
|
|
d1b2a3fca9 | ||
|
|
9dd107bb03 | ||
|
|
6e562eb1e7 | ||
|
|
7d7bfb2034 | ||
|
|
298a5580a9 | ||
|
|
656425a328 | ||
|
|
d10bfd5aa4 | ||
|
|
4e0f89359b | ||
|
|
6ea7dc21eb | ||
|
|
b75b3db232 | ||
|
|
fe87812b34 | ||
|
|
9d0987ed97 | ||
|
|
48f1a8ef38 | ||
|
|
bf7daa8ade | ||
|
|
26006974e8 | ||
|
|
76b1a009e4 | ||
|
|
044b57c927 | ||
|
|
0ad3d5196f | ||
|
|
261e39d8ab | ||
|
|
9069cc889f | ||
|
|
96ed1327f8 | ||
|
|
d60d6713fa | ||
|
|
848d88c122 | ||
|
|
a3dbc3b415 | ||
|
|
ef9f37cd5f | ||
|
|
c035e5a836 | ||
|
|
a2acc02f50 | ||
|
|
590361aeb6 | ||
|
|
b3d7ad0b91 | ||
|
|
e76a5969e8 | ||
|
|
e9b1ad9558 | ||
|
|
1cdf8b232d | ||
|
|
059e787cb5 | ||
|
|
16c525b2c0 | ||
|
|
cd599c9e64 | ||
|
|
2963e5c954 | ||
|
|
00ce8277aa | ||
|
|
70222ffc1a | ||
|
|
dae77d8d43 | ||
|
|
a575fd70ec | ||
|
|
28b56521f5 | ||
|
|
11d0e7aaf1 | ||
|
|
7fd76eff05 | ||
|
|
4af04d8f49 | ||
|
|
eed2a0d06b | ||
|
|
d49363a5af | ||
|
|
0e2cb9fd06 | ||
|
|
661e5eb084 | ||
|
|
cec035c6e0 | ||
|
|
3679be3721 | ||
|
|
67727deb0a | ||
|
|
caa15c5c02 | ||
|
|
d1312c3143 | ||
|
|
f049867cd9 | ||
|
|
2c8045343c | ||
|
|
db06c31305 | ||
|
|
b0077f0b5e | ||
|
|
f310dc0916 | ||
|
|
3c973fa7ce | ||
|
|
d310abed44 | ||
|
|
a9b9251756 | ||
|
|
c66be2e974 | ||
|
|
ca68b9e7a9 | ||
|
|
e0d3efec6e | ||
|
|
4529bd8d0e | ||
|
|
b8d0fee17f | ||
|
|
43179bb44e | ||
|
|
fa8af3421a | ||
|
|
ac9335d111 | ||
|
|
7c0cf8cc23 | ||
|
|
fa7487629f | ||
|
|
6eb47bdb03 | ||
|
|
3c9e97ce00 | ||
|
|
a9fdaa6734 | ||
|
|
41e8f1db73 | ||
|
|
b08d0b5551 | ||
|
|
d3dc453cb0 | ||
|
|
2ef201e43f | ||
|
|
acd914f02d | ||
|
|
0cf100c180 | ||
|
|
26351a81b2 | ||
|
|
c8d07f66d1 | ||
|
|
6b0df31e5d | ||
|
|
96e2bedc10 | ||
|
|
86a54a2658 | ||
|
|
648b61d1cc | ||
|
|
0685cd8aae | ||
|
|
8586c5497b | ||
|
|
90805dd131 | ||
|
|
888a465232 | ||
|
|
639a7dd73a | ||
|
|
afd9f17b73 | ||
|
|
fd40aceabb | ||
|
|
7a8061818e | ||
|
|
f6dfb42a64 | ||
|
|
bc90fe4c71 | ||
|
|
bbf7fd5372 | ||
|
|
8dda052c7d | ||
|
|
1b494fb061 | ||
|
|
4335e5f84c | ||
|
|
30025d7676 | ||
|
|
6dbc13627a | ||
|
|
7566f89229 | ||
|
|
3120260ed6 | ||
|
|
1756b23aea | ||
|
|
0834eca8d4 | ||
|
|
6d2224f1ba | ||
|
|
54b65107b1 | ||
|
|
3b8a017257 | ||
|
|
d4192abce1 | ||
|
|
0fa71ddf7e | ||
|
|
823a860250 | ||
|
|
f05a408a8d | ||
|
|
0c4b28488c | ||
|
|
028961ac9f | ||
|
|
9c95109a6b | ||
|
|
03014e2e7f | ||
|
|
78fb98a609 | ||
|
|
d1d55f1686 | ||
|
|
6dcc5572c1 | ||
|
|
3fea5f5396 | ||
|
|
c73c6039c3 | ||
|
|
72169686fe | ||
|
|
be7c389120 | ||
|
|
2dc9cfaf01 | ||
|
|
86f8fb1c70 | ||
|
|
c0f2991e33 | ||
|
|
3a1db02212 | ||
|
|
13514e1951 | ||
|
|
cfc6e6e8eb | ||
|
|
7324b0e514 | ||
|
|
188078467d | ||
|
|
e5cb13588b | ||
|
|
9bfbc93044 | ||
|
|
c5c0795854 | ||
|
|
86430bfb3d | ||
|
|
33ec61345e | ||
|
|
65bebabd70 | ||
|
|
bf7f7f515e | ||
|
|
c42742a58f | ||
|
|
b9aeaf6634 | ||
|
|
aa3ef70ea6 | ||
|
|
21a9ae3459 | ||
|
|
c5afea5b85 | ||
|
|
1fc3fef642 | ||
|
|
2ed0338da8 | ||
|
|
b4eddce090 | ||
|
|
bbcf69c58c | ||
|
|
18f1306d0c | ||
|
|
9c3f8cf2f5 | ||
|
|
673121b828 | ||
|
|
b762fe4c2e | ||
|
|
c922bf23f6 | ||
|
|
f99c09fab7 | ||
|
|
a6d86b9496 | ||
|
|
1004f870e1 | ||
|
|
d3be855b4b | ||
|
|
0cbdbc8122 | ||
|
|
959be92189 | ||
|
|
5934319953 | ||
|
|
8bef32d389 | ||
|
|
b0be5ff8ad | ||
|
|
9d46890dc0 | ||
|
|
a4f742277b | ||
|
|
86bc313f38 | ||
|
|
54d63e774c | ||
|
|
f801b0fc72 | ||
|
|
80296b9497 | ||
|
|
71d911b3aa | ||
|
|
223d0cf787 | ||
|
|
5375b84e3b | ||
|
|
db9e5e5a87 | ||
|
|
64b32841a3 | ||
|
|
cf388b160b | ||
|
|
16d9cb4c98 | ||
|
|
55a4803a4a | ||
|
|
08f4375177 | ||
|
|
f48aa66ccb | ||
|
|
1f430fe3ff | ||
|
|
8fd630a19d | ||
|
|
09c6b84352 | ||
|
|
1f077e7871 | ||
|
|
885dce4082 | ||
|
|
7e146a2057 | ||
|
|
37ea979e56 | ||
|
|
8b1e6140d2 | ||
|
|
0be2d09778 | ||
|
|
a7a8a05c14 | ||
|
|
4cf22e4ec7 | ||
|
|
288a1c2dd1 | ||
|
|
ec9df5c64a | ||
|
|
5f3afaf282 | ||
|
|
638c4a5781 |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -4,7 +4,7 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
open-pull-requests-limit: 3
|
open-pull-requests-limit: 1
|
||||||
allow:
|
allow:
|
||||||
- dependency-type: direct
|
- dependency-type: direct
|
||||||
- dependency-type: indirect
|
- dependency-type: indirect
|
||||||
@@ -12,7 +12,7 @@ updates:
|
|||||||
directory: "/fuzz"
|
directory: "/fuzz"
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
open-pull-requests-limit: 3
|
open-pull-requests-limit: 1
|
||||||
allow:
|
allow:
|
||||||
- dependency-type: direct
|
- dependency-type: direct
|
||||||
- dependency-type: indirect
|
- dependency-type: indirect
|
||||||
|
|||||||
29
.github/workflows/build.yaml
vendored
29
.github/workflows/build.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
- 1.54
|
- "1.60"
|
||||||
target:
|
target:
|
||||||
- x86_64-unknown-linux-gnu
|
- x86_64-unknown-linux-gnu
|
||||||
- x86_64-unknown-linux-musl
|
- x86_64-unknown-linux-musl
|
||||||
@@ -35,26 +35,29 @@ jobs:
|
|||||||
|
|
||||||
- name: Debug Check (default features)
|
- name: Debug Check (default features)
|
||||||
run: |
|
run: |
|
||||||
git rev-list origin/main..$GITHUB_SHA | xargs -t -I % sh -c 'git checkout %; cargo check --all --target=${{ matrix.target }}'
|
git rev-list origin/main..$GITHUB_SHA | xargs -t -I % sh -c 'git checkout %; cargo check --tests --all --target=${{ matrix.target }}'
|
||||||
git checkout $GITHUB_SHA
|
git checkout $GITHUB_SHA
|
||||||
|
|
||||||
- name: Build (default + tdx)
|
- name: Build (default features)
|
||||||
run: cargo rustc --bin cloud-hypervisor --features "tdx" -- -D warnings
|
run: cargo rustc --locked --bin cloud-hypervisor -- -D warnings
|
||||||
|
|
||||||
- name: Build (acpi,kvm)
|
- name: Build (common + kvm)
|
||||||
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,kvm" -- -D warnings
|
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "common,kvm" -- -D warnings
|
||||||
|
|
||||||
- name: Build (kvm)
|
- name: Build (default features + tdx)
|
||||||
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "kvm" -- -D warnings
|
run: cargo rustc --locked --bin cloud-hypervisor --features "tdx" -- -D warnings
|
||||||
|
|
||||||
- name: Build (acpi,mshv)
|
- name: Build (default features + amx)
|
||||||
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,mshv" -- -D warnings
|
run: cargo rustc --locked --bin cloud-hypervisor --features "amx" -- -D warnings
|
||||||
|
|
||||||
- name: Build (mshv)
|
- name: Build (default features + gdb)
|
||||||
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "mshv" -- -D warnings
|
run: cargo rustc --locked --bin cloud-hypervisor --features "gdb" -- -D warnings
|
||||||
|
|
||||||
|
- name: Build (common + mshv)
|
||||||
|
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "common,mshv" -- -D warnings
|
||||||
|
|
||||||
- name: Release Build (default features)
|
- name: Release Build (default features)
|
||||||
run: cargo build --all --release --target=${{ matrix.target }}
|
run: cargo build --locked --all --release --target=${{ matrix.target }}
|
||||||
|
|
||||||
- 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)"
|
||||||
|
|||||||
22
.github/workflows/quality-aarch64.yaml
vendored
22
.github/workflows/quality-aarch64.yaml
vendored
@@ -32,30 +32,16 @@ jobs:
|
|||||||
- name: Formatting (rustfmt)
|
- name: Formatting (rustfmt)
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
|
|
||||||
- name: Clippy (kvm)
|
- name: Clippy (common + kvm)
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
use-cross: true
|
use-cross: true
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --target=${{ matrix.target }} --all --no-default-features --features "kvm" -- -D warnings
|
args: --target=${{ matrix.target }} --tests --all --no-default-features --features "common,kvm" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (kvm,acpi)
|
- name: Clippy (default features)
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
use-cross: true
|
use-cross: true
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --target=${{ matrix.target }} --all --no-default-features --features "kvm,acpi" -- -D warnings
|
args: --target=${{ matrix.target }} --tests --all -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (all features,kvm)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
use-cross: true
|
|
||||||
command: clippy
|
|
||||||
args: --target=${{ matrix.target }} --all --no-default-features --features "common,kvm" -- -D warnings
|
|
||||||
|
|
||||||
- name: Clippy (default)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
use-cross: true
|
|
||||||
command: clippy
|
|
||||||
args: --target=${{ matrix.target }} --all -- -D warnings
|
|
||||||
|
|||||||
29
.github/workflows/quality.yaml
vendored
29
.github/workflows/quality.yaml
vendored
@@ -33,29 +33,20 @@ jobs:
|
|||||||
- name: Formatting (rustfmt)
|
- name: Formatting (rustfmt)
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
|
|
||||||
- name: Clippy (all features,kvm)
|
- name: Clippy (common + kvm)
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "common,kvm" -- -D warnings
|
run: cargo clippy --locked --all --all-targets --no-default-features --tests --features "common,kvm" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (all features,mshv)
|
- name: Clippy (default features)
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "common,mshv" -- -D warnings
|
run: cargo clippy --locked --all --all-targets --tests -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (acpi,kvm)
|
- name: Clippy (default features + amx)
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,kvm" -- -D warnings
|
run: cargo clippy --locked --all --all-targets --tests --features "amx" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (acpi,kvm,tdx)
|
- name: Clippy (default features + gdb)
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,kvm,tdx" -- -D warnings
|
run: cargo clippy --locked --all --all-targets --tests --features "gdb" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (kvm)
|
- name: Clippy (common + mshv)
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "kvm" -- -D warnings
|
run: cargo clippy --locked --all --all-targets --no-default-features --tests --features "common,mshv" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (acpi,mshv)
|
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "acpi,mshv" -- -D warnings
|
|
||||||
|
|
||||||
- name: Clippy (mshv)
|
|
||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "mshv" -- -D warnings
|
|
||||||
|
|
||||||
- name: Clippy (integration tests)
|
|
||||||
run: cargo clippy --all --all-targets --tests -- -D warnings
|
|
||||||
|
|
||||||
- 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)"
|
||||||
|
|||||||
18
.github/workflows/release.yaml
vendored
18
.github/workflows/release.yaml
vendored
@@ -16,23 +16,31 @@ jobs:
|
|||||||
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
|
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: "1.60"
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
|
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: "1.60"
|
||||||
target: x86_64-unknown-linux-musl
|
target: x86_64-unknown-linux-musl
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --all --release --target=x86_64-unknown-linux-gnu
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
toolchain: "1.60"
|
||||||
|
command: build
|
||||||
|
args: --all --release --target=x86_64-unknown-linux-gnu
|
||||||
- name: Static Build
|
- name: Static Build
|
||||||
run: cargo build --all --release --target=x86_64-unknown-linux-musl
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
toolchain: "1.60"
|
||||||
|
command: build
|
||||||
|
args: --all --release --target=x86_64-unknown-linux-musl
|
||||||
- name: Strip cloud-hypervisor binaries
|
- name: Strip cloud-hypervisor binaries
|
||||||
run: strip target/*/release/cloud-hypervisor
|
run: strip target/*/release/cloud-hypervisor
|
||||||
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
|
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: "1.60"
|
||||||
target: aarch64-unknown-linux-musl
|
target: aarch64-unknown-linux-musl
|
||||||
override: true
|
override: true
|
||||||
- name: Static Build (AArch64)
|
- name: Static Build (AArch64)
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@
|
|||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
**/Cargo.lock
|
**/Cargo.lock
|
||||||
**/rusty-tags.vi
|
**/rusty-tags.vi
|
||||||
|
/rpm/SOURCES
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
edition = "2018"
|
edition = "2021"
|
||||||
2
CODEOWNERS
Normal file
2
CODEOWNERS
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Add the list of code owners here (using their GitHub username)
|
||||||
|
* @cloud-hypervisor/cloud-hypervisor-reviewers
|
||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
Cloud Hypervisor is an open source project licensed under the [Apache v2
|
Cloud Hypervisor is an open source project licensed under the [Apache v2
|
||||||
License](https://opensource.org/licenses/Apache-2.0) and the [BSD 3
|
License](https://opensource.org/licenses/Apache-2.0) and the [BSD 3
|
||||||
Clause](https://opensource.org/licenses/BSD-3-Clause) license. Contributions
|
Clause](https://opensource.org/licenses/BSD-3-Clause) license. Individual files
|
||||||
can be made under either license or both. Individual files contain details of
|
contain details of their licensing and changes to that file are under the same
|
||||||
their licensing and changes to that file are under the same license unless the
|
license unless the contribution changes the license of the file. When importing
|
||||||
contribution changes the license of the file. When importing code from a third
|
code from a third party project (e.g. Firecracker or CrosVM) please respect the
|
||||||
party project (e.g. Firecracker or CrosVM) please respect the license of those
|
license of those projects.
|
||||||
projects.
|
|
||||||
|
New code should be under the [Apache v2
|
||||||
|
License](https://opensource.org/licenses/Apache-2.0).
|
||||||
|
|
||||||
## Coding Style
|
## Coding Style
|
||||||
|
|
||||||
@@ -63,11 +65,9 @@ you want to merge your changes to `cloud-hypervisor`:
|
|||||||
2. Within your fork, create a branch for your contribution.
|
2. Within your fork, create a branch for your contribution.
|
||||||
3. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
|
3. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
|
||||||
against the main branch of the Cloud Hypervisor repository.
|
against the main branch of the Cloud Hypervisor repository.
|
||||||
4. Add reviewers to your pull request and then work with your reviewers to address
|
4. To update your pull request amend existing commits whenever applicable and
|
||||||
any comments and obtain minimum of 2 [maintainers](MAINTAINERS.md) approvals.
|
|
||||||
To update your pull request amend existing commits whenever applicable and
|
|
||||||
then push the new changes to your pull request branch.
|
then push the new changes to your pull request branch.
|
||||||
5. Once the pull request is approved, one of the maintainers will merge it.
|
5. Once the pull request is approved it can be integrated.
|
||||||
|
|
||||||
## Issue tracking
|
## Issue tracking
|
||||||
|
|
||||||
|
|||||||
267
Cargo.lock
generated
267
Cargo.lock
generated
@@ -20,9 +20,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.55"
|
version = "1.0.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
|
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -50,7 +50,6 @@ dependencies = [
|
|||||||
"linux-loader",
|
"linux-loader",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
@@ -131,24 +130,33 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.1.5"
|
version = "3.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ced1892c55c910c1219e98d6fc8d71f6bddba7905866ce740066d8bfea859312"
|
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"clap_lex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"os_str_bytes",
|
|
||||||
"strsim",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"terminal_size",
|
"terminal_size",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "22.0.0"
|
version = "24.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -175,9 +183,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.1"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee6b9c9389584bcba988bd0836086789b7f87ad91892d6a83d5291dbb24524b5"
|
checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -219,9 +227,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.3.6"
|
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 = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
@@ -257,7 +265,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -293,9 +300,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
|
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -344,7 +351,6 @@ dependencies = [
|
|||||||
"mshv-bindings",
|
"mshv-bindings",
|
||||||
"mshv-ioctls",
|
"mshv-ioctls",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -363,9 +369,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@@ -400,10 +406,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "ipnetwork"
|
||||||
version = "1.0.1"
|
version = "0.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
checksum = "1f84f1612606f3753f205a4e9a2efd6fe5b4c573a6269b2cc6c3003d44a0d127"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-bindings"
|
name = "kvm-bindings"
|
||||||
@@ -433,9 +448,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.119"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libssh2-sys"
|
name = "libssh2-sys"
|
||||||
@@ -453,9 +468,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libz-sys"
|
name = "libz-sys"
|
||||||
version = "1.1.3"
|
version = "1.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66"
|
checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -474,18 +489,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
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 = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
|
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -498,9 +514,9 @@ checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
@@ -514,7 +530,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-bindings"
|
name = "mshv-bindings"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#d241ffcacdfa4240b4a1d34b44af89dc7b113986"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#67e13faa36989a9226ad21c9ff3947e1d5738a54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -526,7 +542,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-ioctls"
|
name = "mshv-ioctls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#d241ffcacdfa4240b4a1d34b44af89dc7b113986"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#67e13faa36989a9226ad21c9ff3947e1d5738a54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mshv-bindings",
|
"mshv-bindings",
|
||||||
@@ -564,28 +580,34 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "no-std-net"
|
||||||
version = "0.2.14"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-src"
|
name = "openssl-src"
|
||||||
version = "111.17.0+1.1.1m"
|
version = "111.20.0+1.1.1o"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05d6a336abd10814198f66e2a91ccd7336611f30334119ca8ce300536666fcf4"
|
checksum = "92892c4f87d56e376e469ace79f1128fdaded07646ddf73aa0be4706ff712dec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.72"
|
version = "0.9.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
|
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -601,12 +623,9 @@ version = "0.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435"
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
@@ -635,9 +654,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pci"
|
name = "pci"
|
||||||
@@ -649,7 +668,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
@@ -670,7 +688,6 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"dirs",
|
"dirs",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"test_infra",
|
"test_infra",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -679,17 +696,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet"
|
name = "pnet"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8750e073f82219c01e771133c64718d7685aef922da8a0d430a46aed05b6341a"
|
checksum = "d5cc57672f576f6b95370277fb445738d4887195c6cf4192bdf4f44697e2389b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork 0.19.0",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
"pnet_datalink",
|
"pnet_datalink",
|
||||||
"pnet_packet",
|
"pnet_packet",
|
||||||
@@ -699,17 +716,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_base"
|
name = "pnet_base"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8205fe084bd43a3af79b3155c19feddd62e733640498842e631a2ffe107d1538"
|
checksum = "2e88341c6c842f89bdc7287f7b1e26b6fa64fa11c7ea3756971e6f18cd2510c4"
|
||||||
|
dependencies = [
|
||||||
|
"no-std-net",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_datalink"
|
name = "pnet_datalink"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f85aef5e52e22ff06b1b11f2eb6d52959a9e0ecad3cb3f5cc2d78cadc077f0e"
|
checksum = "bc6e55d71c51db73372db35bc54f43abd8460adff1c3a9b717804ca6416d5df2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork 0.18.0",
|
||||||
"libc",
|
"libc",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
"pnet_sys",
|
"pnet_sys",
|
||||||
@@ -718,9 +738,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros"
|
name = "pnet_macros"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98cc3af95fed6dc318dfede3e81320f96ad5e237c6f7c4688108b19c8e67432d"
|
checksum = "ebfcdc9c072966723026b3596a1f655fb8bbfe0142f9770f8d481aee4459d6b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -730,18 +750,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros_support"
|
name = "pnet_macros_support"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "feaba58ba96abb218ec584d6caf0d3ff48922df05dbbeb1560553c197091b29e"
|
checksum = "bba532f5a4b320c029d89e612671fb621851b3b07e972c53850d34130033a5cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_packet"
|
name = "pnet_packet"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f246edaaf1aaf82072d4cd38ee18bcc5dfc0464093f9ca39e4ac5962d68cf9d4"
|
checksum = "7009716ac86091c1b6e2cdec95a2b028c880f516054c1ec11edd02f9f463cbde"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -751,9 +771,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_sys"
|
name = "pnet_sys"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "028c87a5e3a48fc07df099a2025f2ef16add5993712e1494ba69a6707ee7ed06"
|
checksum = "8e2a05efbc55c22f664c0ea475fbc4ffc4d09346aff9068438279d7e3d431f6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -761,9 +781,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_transport"
|
name = "pnet_transport"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "950f2a7961e19d22e19e84ff0a6e0955013185fe149673499662633d02b41b7a"
|
checksum = "75b8ff06f37863f7590183f7044ab2e8d4dae991ecea0c791e3c6dd61ed2913d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -773,11 +793,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.36"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -793,9 +813,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.15"
|
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 = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -811,28 +831,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.11"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
|
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.0"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.5.4"
|
version = "1.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -841,15 +862,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.25"
|
version = "0.6.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remain"
|
name = "remain"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7"
|
checksum = "0c35270ea384ac1762895831cc8acb96f171468e52cec82ed9186f9416209fa4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -867,9 +888,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.9"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
@@ -888,21 +909,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.6"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
|
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -911,9 +935,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.79"
|
version = "1.0.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -922,9 +946,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
|
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -971,13 +995,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.86"
|
version = "1.0.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-xid",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1035,18 +1059,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.30"
|
version = "1.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.30"
|
version = "1.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1054,16 +1078,22 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-ident"
|
||||||
version = "0.2.2"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "0.8.2"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
@@ -1160,9 +1190,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b56bf8f178fc500fe14505fca8b00dec76fc38f2304f461c8d9d7547982311d"
|
checksum = "53567fd9ab820e4f3cc156f24146882fee3c365194c3e1dea74723265f27fc88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1172,8 +1202,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost-user-backend"
|
name = "vhost-user-backend"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/rust-vmm/vhost-user-backend?branch=main#bbc892ba4526bdf8101252f7aa51832d1f2eeabd"
|
source = "git+https://github.com/rust-vmm/vhost-user-backend?rev=14f58eda14076e973704d4f904850be1146fbb05#14f58eda14076e973704d4f904850be1146fbb05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
@@ -1246,8 +1276,8 @@ dependencies = [
|
|||||||
"rate_limiter",
|
"rate_limiter",
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
@@ -1263,8 +1293,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-queue"
|
name = "virtio-queue"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/rust-vmm/vm-virtio?branch=main#bbb22d43558a76cc7cc9c262c4be870a9e682a86"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88f2d73c184c18f8acc32dab77fcb6e3af92d53262538d3a68aa474810d6863c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -1285,8 +1316,8 @@ name = "vm-device"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"hypervisor",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"vfio-ioctls",
|
"vfio-ioctls",
|
||||||
@@ -1301,9 +1332,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#ca35d96191f8232bd7a
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "339d4349c126fdcd87e034631d7274370cf19eb0e87b33166bcd956589fc72c5"
|
checksum = "767ed8aaebbff902e02e6d3749dc2baef55e46565f8a6414a065e5baee4b4a81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1316,7 +1347,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
@@ -1362,7 +1392,6 @@ dependencies = [
|
|||||||
"qcow",
|
"qcow",
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|||||||
32
Cargo.toml
32
Cargo.toml
@@ -1,8 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "22.0.0"
|
version = "24.0.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
default-run = "cloud-hypervisor"
|
default-run = "cloud-hypervisor"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
license = "LICENSE-APACHE & LICENSE-BSD-3-Clause"
|
license = "LICENSE-APACHE & LICENSE-BSD-3-Clause"
|
||||||
@@ -10,52 +10,51 @@ description = "Open source Virtual Machine Monitor (VMM) that runs on top of KVM
|
|||||||
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
||||||
# Minimum buildable version:
|
# Minimum buildable version:
|
||||||
# Keep in sync with version in .github/workflows/build.yaml
|
# Keep in sync with version in .github/workflows/build.yaml
|
||||||
rust-version = "1.54"
|
rust-version = "1.60"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.55"
|
anyhow = "1.0.57"
|
||||||
api_client = { path = "api_client" }
|
api_client = { path = "api_client" }
|
||||||
clap = { version = "3.1.5", features = ["wrap_help","cargo"] }
|
clap = { version = "3.1.18", features = ["wrap_help","cargo"] }
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
event_monitor = { path = "event_monitor" }
|
event_monitor = { path = "event_monitor" }
|
||||||
hypervisor = { path = "hypervisor" }
|
hypervisor = { path = "hypervisor" }
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = { version = "0.4.14", features = ["std"] }
|
log = { version = "0.4.17", features = ["std"] }
|
||||||
option_parser = { path = "option_parser" }
|
option_parser = { path = "option_parser" }
|
||||||
seccompiler = "0.2.0"
|
seccompiler = "0.2.0"
|
||||||
serde_json = "1.0.79"
|
serde_json = "1.0.81"
|
||||||
signal-hook = "0.3.13"
|
signal-hook = "0.3.14"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.31"
|
||||||
vmm = { path = "vmm" }
|
vmm = { path = "vmm" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
vm-memory = "0.7.0"
|
vm-memory = "0.8.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "3.1.5", features = ["wrap_help"] }
|
clap = { version = "3.1.18", features = ["cargo"] }
|
||||||
|
|
||||||
# List of patched crates
|
# List of patched crates
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0-tdx" }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.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" }
|
||||||
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio", branch = "main" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
lazy_static= "1.4.0"
|
lazy_static= "1.4.0"
|
||||||
net_util = { path = "net_util" }
|
net_util = { path = "net_util" }
|
||||||
serde_json = "1.0.79"
|
serde_json = "1.0.81"
|
||||||
test_infra = { path = "test_infra" }
|
test_infra = { path = "test_infra" }
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["common", "kvm"]
|
default = ["common", "kvm"]
|
||||||
# Common features for all hypervisors
|
# Common features for all hypervisors
|
||||||
common = ["acpi", "cmos", "fwdebug"]
|
common = ["fwdebug"]
|
||||||
acpi = ["vmm/acpi"]
|
amx = ["vmm/amx"]
|
||||||
cmos = ["vmm/cmos"]
|
cmos = ["vmm/cmos"]
|
||||||
fwdebug = ["vmm/fwdebug"]
|
fwdebug = ["vmm/fwdebug"]
|
||||||
gdb = ["vmm/gdb"]
|
gdb = ["vmm/gdb"]
|
||||||
@@ -79,6 +78,7 @@ members = [
|
|||||||
"performance-metrics",
|
"performance-metrics",
|
||||||
"qcow",
|
"qcow",
|
||||||
"rate_limiter",
|
"rate_limiter",
|
||||||
|
"test_infra",
|
||||||
"vfio_user",
|
"vfio_user",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"vhost_user_block",
|
"vhost_user_block",
|
||||||
|
|||||||
137
Jenkinsfile
vendored
137
Jenkinsfile
vendored
@@ -43,7 +43,7 @@ pipeline{
|
|||||||
stage ('Build') {
|
stage ('Build') {
|
||||||
parallel {
|
parallel {
|
||||||
stage ('Worker build') {
|
stage ('Worker build') {
|
||||||
agent { node { label 'hirsute' } }
|
agent { node { label 'focal' } }
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
expression {
|
expression {
|
||||||
@@ -56,7 +56,11 @@ pipeline{
|
|||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage ('Prepare environment') {
|
||||||
|
steps {
|
||||||
|
sh "scripts/prepare_vdpa.sh"
|
||||||
|
}
|
||||||
|
}
|
||||||
stage ('Run OpenAPI tests') {
|
stage ('Run OpenAPI tests') {
|
||||||
steps {
|
steps {
|
||||||
sh "scripts/run_openapi_tests.sh"
|
sh "scripts/run_openapi_tests.sh"
|
||||||
@@ -115,7 +119,7 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Worker build (musl)') {
|
stage ('Worker build (musl)') {
|
||||||
agent { node { label 'hirsute' } }
|
agent { node { label 'focal' } }
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
expression {
|
expression {
|
||||||
@@ -128,7 +132,11 @@ pipeline{
|
|||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage ('Prepare environment') {
|
||||||
|
steps {
|
||||||
|
sh "scripts/prepare_vdpa.sh"
|
||||||
|
}
|
||||||
|
}
|
||||||
stage ('Run unit tests for musl') {
|
stage ('Run unit tests for musl') {
|
||||||
steps {
|
steps {
|
||||||
sh "scripts/dev_cli.sh tests --unit --libc musl"
|
sh "scripts/dev_cli.sh tests --unit --libc musl"
|
||||||
@@ -145,90 +153,8 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Worker build SGX') {
|
|
||||||
agent { node { label 'bionic-sgx' } }
|
|
||||||
when {
|
|
||||||
beforeAgent true
|
|
||||||
allOf {
|
|
||||||
branch 'main'
|
|
||||||
expression {
|
|
||||||
return runWorkers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage ('Checkout') {
|
|
||||||
steps {
|
|
||||||
checkout scm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Run SGX integration tests') {
|
|
||||||
options {
|
|
||||||
timeout(time: 1, unit: 'HOURS')
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
sh "scripts/dev_cli.sh tests --integration-sgx"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Run SGX integration tests for musl') {
|
|
||||||
options {
|
|
||||||
timeout(time: 1, unit: 'HOURS')
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
sh "scripts/dev_cli.sh tests --integration-sgx --libc musl"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
|
||||||
deleteDir()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Worker build VFIO') {
|
|
||||||
agent { node { label 'bionic-vfio' } }
|
|
||||||
when {
|
|
||||||
beforeAgent true
|
|
||||||
allOf {
|
|
||||||
branch 'main'
|
|
||||||
expression {
|
|
||||||
return runWorkers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage ('Checkout') {
|
|
||||||
steps {
|
|
||||||
checkout scm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Run VFIO integration tests') {
|
|
||||||
options {
|
|
||||||
timeout(time: 1, unit: 'HOURS')
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
sh "scripts/dev_cli.sh tests --integration-vfio"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Run VFIO integration tests for musl') {
|
|
||||||
options {
|
|
||||||
timeout(time: 1, unit: 'HOURS')
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
sh "scripts/dev_cli.sh tests --integration-vfio --libc musl"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
|
||||||
deleteDir()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Worker build - Windows guest') {
|
stage ('Worker build - Windows guest') {
|
||||||
agent { node { label 'hirsute' } }
|
agent { node { label 'focal' } }
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
expression {
|
expression {
|
||||||
@@ -274,7 +200,7 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Worker build - Live Migration') {
|
stage ('Worker build - Live Migration') {
|
||||||
agent { node { label 'hirsute-small' } }
|
agent { node { label 'focal-small' } }
|
||||||
when {
|
when {
|
||||||
beforeAgent true
|
beforeAgent true
|
||||||
expression {
|
expression {
|
||||||
@@ -307,39 +233,6 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Worker build - Metrics') {
|
|
||||||
agent { node { label 'focal-metrics' } }
|
|
||||||
when {
|
|
||||||
branch 'main'
|
|
||||||
beforeAgent true
|
|
||||||
expression {
|
|
||||||
return runWorkers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
environment {
|
|
||||||
METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage ('Checkout') {
|
|
||||||
steps {
|
|
||||||
checkout scm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Run metrics tests') {
|
|
||||||
options {
|
|
||||||
timeout(time: 1, unit: 'HOURS')
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage ('Upload metrics report') {
|
|
||||||
steps {
|
|
||||||
sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +272,7 @@ def cancelPreviousBuilds() {
|
|||||||
def installAzureCli() {
|
def installAzureCli() {
|
||||||
sh "sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg"
|
sh "sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg"
|
||||||
sh "curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null"
|
sh "curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null"
|
||||||
sh "echo \"deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ hirsute main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
|
sh "echo \"deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ focal main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
|
||||||
sh "sudo apt update"
|
sh "sudo apt update"
|
||||||
sh "sudo apt install -y azure-cli"
|
sh "sudo apt install -y azure-cli"
|
||||||
}
|
}
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -88,12 +88,10 @@ Hypervisor. Here, all the steps are based on Ubuntu, for other Linux
|
|||||||
distributions please replace the package manager and package name.
|
distributions please replace the package manager and package name.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Install git
|
# Install build-essential, git, and qemu-img
|
||||||
$ sudo apt install git
|
$ sudo apt install git build-essential qemu-img
|
||||||
# Install rust tool chain
|
# Install rust tool chain
|
||||||
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
# Install build-essential
|
|
||||||
$ sudo apt install build-essential
|
|
||||||
# If you want to build statically linked binary please add musl target
|
# If you want to build statically linked binary please add musl target
|
||||||
$ rustup target add x86_64-unknown-linux-musl
|
$ rustup target add x86_64-unknown-linux-musl
|
||||||
```
|
```
|
||||||
@@ -168,7 +166,7 @@ cloud image. Here we will use a Ubuntu image:
|
|||||||
$ pushd $CLOUDH
|
$ pushd $CLOUDH
|
||||||
$ wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
|
$ wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
|
||||||
$ qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
|
$ qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
|
||||||
$ wget https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/download/0.3.2/hypervisor-fw
|
$ wget https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/download/0.4.0/hypervisor-fw
|
||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -267,30 +265,32 @@ Cloud Hypervisor is under active development. The following stability guarantees
|
|||||||
are currently made:
|
are currently made:
|
||||||
|
|
||||||
* The API (including command line options) will not be removed or changed in a
|
* The API (including command line options) will not be removed or changed in a
|
||||||
breaking way without a minimum of 2 releases notice. Where possible warnings
|
breaking way without a minimum of 2 major releases notice. Where possible
|
||||||
will be given about the use of deprecated functionality and the deprecations
|
warnings will be given about the use of deprecated functionality and the
|
||||||
will be documented in the release notes.
|
deprecations will be documented in the release notes.
|
||||||
|
|
||||||
* Point releases will be made between individual releases where there are
|
* Point releases will be made between individual releases where there are
|
||||||
substantial bug fixes or security issues that need to be fixed.
|
substantial bug fixes or security issues that need to be fixed. These point
|
||||||
|
releases will only include bug fixes.
|
||||||
|
|
||||||
Currently the following items are **not** guaranteed across updates:
|
Currently the following items are **not** guaranteed across updates:
|
||||||
|
|
||||||
* Snapshot/restore is not supported across different versions
|
* Snapshot/restore is not supported across different versions
|
||||||
* Live migration is not supported across different versions
|
* Live migration is not supported across different versions
|
||||||
* The following features are considered experimental and may change
|
* The following features are considered experimental and may change
|
||||||
substantially between releases: TDX, SGX.
|
substantially between releases: TDX, vfio-user, vDPA.
|
||||||
|
|
||||||
|
As of 2022-04-05, the following cloud images are supported:
|
||||||
As of 2021-04-29, the following cloud images are supported:
|
|
||||||
|
|
||||||
- [Ubuntu Bionic](https://cloud-images.ubuntu.com/bionic/current/) (cloudimg)
|
- [Ubuntu Bionic](https://cloud-images.ubuntu.com/bionic/current/) (cloudimg)
|
||||||
- [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (cloudimg)
|
- [Ubuntu Focal](https://cloud-images.ubuntu.com/focal/current/) (cloudimg)
|
||||||
- [Ubuntu Groovy](https://cloud-images.ubuntu.com/groovy/current/) (cloudimg)
|
- [Ubuntu Jammy](https://cloud-images.ubuntu.com/jammy/current/) (cloudimg)
|
||||||
- [Ubuntu Hirsute](https://cloud-images.ubuntu.com/hirsute/current/) (cloudimg)
|
|
||||||
|
|
||||||
Direct kernel boot to userspace should work with a rootfs from most
|
Direct kernel boot to userspace should work with a rootfs from most
|
||||||
distributions.
|
distributions.
|
||||||
|
|
||||||
|
Further details can be found in the [release documentation](docs/releases.md).
|
||||||
|
|
||||||
## Hot Plug
|
## Hot Plug
|
||||||
|
|
||||||
Cloud Hypervisor supports hotplug of CPUs, passthrough devices (VFIO),
|
Cloud Hypervisor supports hotplug of CPUs, passthrough devices (VFIO),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "acpi_tables"
|
name = "acpi_tables"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vm-memory = "0.7.0"
|
vm-memory = "0.8.0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "api_client"
|
name = "api_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
@@ -2,27 +2,25 @@
|
|||||||
name = "arch"
|
name = "arch"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
acpi = ["acpi_tables"]
|
|
||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables" }
|
||||||
anyhow = "1.0.55"
|
anyhow = "1.0.57"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
linux-loader = { version = "0.4.0", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.4.0", features = ["elf", "bzimage", "pe"] }
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
serde = { version = "1.0.136", features = ["rc"] }
|
serde = { version = "1.0.137", features = ["rc", "derive"] }
|
||||||
serde_derive = "1.0.136"
|
thiserror = "1.0.31"
|
||||||
thiserror = "1.0.30"
|
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-bitmap"] }
|
vm-memory = { version = "0.8.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,13 @@ use std::str;
|
|||||||
use super::super::DeviceType;
|
use super::super::DeviceType;
|
||||||
use super::super::GuestMemoryMmap;
|
use super::super::GuestMemoryMmap;
|
||||||
use super::super::InitramfsConfig;
|
use super::super::InitramfsConfig;
|
||||||
use super::get_fdt_addr;
|
|
||||||
use super::gic::GicDevice;
|
use super::gic::GicDevice;
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
|
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
|
||||||
PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
|
PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
|
||||||
};
|
};
|
||||||
use vm_fdt::{FdtWriter, FdtWriterResult};
|
use vm_fdt::{FdtWriter, FdtWriterResult};
|
||||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
||||||
|
|
||||||
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
|
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
|
||||||
const GIC_PHANDLE: u32 = 1;
|
const GIC_PHANDLE: u32 = 1;
|
||||||
@@ -141,9 +140,8 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
|
|
||||||
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
||||||
// Write FDT to memory.
|
// Write FDT to memory.
|
||||||
let fdt_address = GuestAddress(get_fdt_addr());
|
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(fdt_final.as_slice(), fdt_address)
|
.write_slice(fdt_final.as_slice(), super::layout::FDT_START)
|
||||||
.map_err(Error::WriteFdtToMemory)?;
|
.map_err(Error::WriteFdtToMemory)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -231,40 +229,67 @@ fn create_memory_node(
|
|||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
numa_nodes: &NumaNodes,
|
numa_nodes: &NumaNodes,
|
||||||
) -> FdtWriterResult<()> {
|
) -> FdtWriterResult<()> {
|
||||||
|
// See https://github.com/torvalds/linux/blob/58ae0b51506802713aa0e9956d1853ba4c722c98/Documentation/devicetree/bindings/numa.txt
|
||||||
|
// for NUMA setting in memory node.
|
||||||
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() {
|
||||||
let numa_node = numa_nodes.get(&(numa_node_idx as u32));
|
let numa_node = numa_nodes.get(&(numa_node_idx as u32));
|
||||||
|
let mut mem_reg_prop: Vec<u64> = Vec::new();
|
||||||
|
let mut node_memory_addr: u64 = 0;
|
||||||
// Each memory zone of numa will have its own memory node, but
|
// Each memory zone of numa will have its own memory node, but
|
||||||
// different numa nodes should not share same memory zones.
|
// different numa nodes should not share same memory zones.
|
||||||
for memory_region in numa_node.unwrap().memory_regions.iter() {
|
for memory_region in numa_node.unwrap().memory_regions.iter() {
|
||||||
let memory_region_start_addr: u64 = memory_region.start_addr().raw_value();
|
let memory_region_start_addr: u64 = memory_region.start_addr().raw_value();
|
||||||
let memory_region_size: u64 = memory_region.size() as u64;
|
let memory_region_size: u64 = memory_region.size() as u64;
|
||||||
let mem_reg_prop = [memory_region_start_addr, memory_region_size];
|
mem_reg_prop.push(memory_region_start_addr);
|
||||||
// With feature `acpi` enabled, RAM at 0-4M is for edk2 only
|
mem_reg_prop.push(memory_region_size);
|
||||||
// and should be hidden to the guest.
|
// Set the node address the first non-zero regison address
|
||||||
#[cfg(feature = "acpi")]
|
if node_memory_addr == 0 {
|
||||||
if memory_region_start_addr == 0 {
|
node_memory_addr = memory_region_start_addr;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let memory_node_name = format!("memory@{:x}", memory_region_start_addr);
|
|
||||||
let memory_node = fdt.begin_node(&memory_node_name)?;
|
|
||||||
fdt.property_string("device_type", "memory")?;
|
|
||||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
|
||||||
fdt.property_u32("numa-node-id", numa_node_idx as u32)?;
|
|
||||||
fdt.end_node(memory_node)?;
|
|
||||||
}
|
}
|
||||||
|
let memory_node_name = format!("memory@{:x}", node_memory_addr);
|
||||||
|
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||||
|
fdt.property_string("device_type", "memory")?;
|
||||||
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
fdt.property_u32("numa-node-id", numa_node_idx as u32)?;
|
||||||
|
fdt.end_node(memory_node)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mem_size = guest_mem.last_addr().raw_value() - super::layout::RAM_64BIT_START + 1;
|
let last_addr = guest_mem.last_addr().raw_value();
|
||||||
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
|
if last_addr < super::layout::MEM_32BIT_RESERVED_START.raw_value() {
|
||||||
// for an explanation of this.
|
// Case 1: all RAM is under the hole
|
||||||
let mem_reg_prop = [super::layout::RAM_64BIT_START as u64, mem_size as u64];
|
let mem_size = last_addr - super::layout::RAM_START.raw_value() + 1;
|
||||||
let memory_node = fdt.begin_node("memory")?;
|
let mem_reg_prop = [super::layout::RAM_START.raw_value() as u64, mem_size as u64];
|
||||||
|
let memory_node = fdt.begin_node("memory")?;
|
||||||
|
fdt.property_string("device_type", "memory")?;
|
||||||
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
fdt.end_node(memory_node)?;
|
||||||
|
} else {
|
||||||
|
// Case 2: RAM is split by the hole
|
||||||
|
// Region 1: RAM before the hole
|
||||||
|
let mem_size = super::layout::MEM_32BIT_RESERVED_START.raw_value()
|
||||||
|
- super::layout::RAM_START.raw_value();
|
||||||
|
let mem_reg_prop = [super::layout::RAM_START.raw_value() as u64, mem_size as u64];
|
||||||
|
let memory_node_name = format!("memory@{:x}", super::layout::RAM_START.raw_value());
|
||||||
|
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||||
|
fdt.property_string("device_type", "memory")?;
|
||||||
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
fdt.end_node(memory_node)?;
|
||||||
|
|
||||||
fdt.property_string("device_type", "memory")?;
|
// Region 2: RAM after the hole
|
||||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
let mem_size = last_addr - super::layout::RAM_64BIT_START.raw_value() + 1;
|
||||||
fdt.end_node(memory_node)?;
|
let mem_reg_prop = [
|
||||||
|
super::layout::RAM_64BIT_START.raw_value() as u64,
|
||||||
|
mem_size as u64,
|
||||||
|
];
|
||||||
|
let memory_node_name =
|
||||||
|
format!("memory@{:x}", super::layout::RAM_64BIT_START.raw_value());
|
||||||
|
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||||
|
fdt.property_string("device_type", "memory")?;
|
||||||
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
fdt.end_node(memory_node)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -548,20 +573,19 @@ fn create_pci_nodes(
|
|||||||
// could fall bellow 4G.
|
// could fall bellow 4G.
|
||||||
// Here we cut off PCI device space below 8G in FDT to workaround the EDK2 check.
|
// Here we cut off PCI device space below 8G in FDT to workaround the EDK2 check.
|
||||||
// But the address written in ACPI is not impacted.
|
// But the address written in ACPI is not impacted.
|
||||||
let (pci_device_base_64bit, pci_device_size_64bit) = if cfg!(feature = "acpi")
|
let (pci_device_base_64bit, pci_device_size_64bit) =
|
||||||
&& (pci_device_info_elem.pci_device_space_start < PCI_HIGH_BASE)
|
if pci_device_info_elem.pci_device_space_start < PCI_HIGH_BASE.raw_value() {
|
||||||
{
|
(
|
||||||
(
|
PCI_HIGH_BASE.raw_value(),
|
||||||
PCI_HIGH_BASE,
|
pci_device_info_elem.pci_device_space_size
|
||||||
pci_device_info_elem.pci_device_space_size
|
- (PCI_HIGH_BASE.raw_value() - pci_device_info_elem.pci_device_space_start),
|
||||||
- (PCI_HIGH_BASE - pci_device_info_elem.pci_device_space_start),
|
)
|
||||||
)
|
} else {
|
||||||
} else {
|
(
|
||||||
(
|
pci_device_info_elem.pci_device_space_start,
|
||||||
pci_device_info_elem.pci_device_space_start,
|
pci_device_info_elem.pci_device_space_size,
|
||||||
pci_device_info_elem.pci_device_space_size,
|
)
|
||||||
)
|
};
|
||||||
};
|
|
||||||
// There is no specific requirement of the 32bit MMIO range, and
|
// There is no specific requirement of the 32bit MMIO range, and
|
||||||
// therefore at least we can make these ranges 4K aligned.
|
// therefore at least we can make these ranges 4K aligned.
|
||||||
let pci_device_size_32bit: u64 =
|
let pci_device_size_32bit: u64 =
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ pub mod kvm {
|
|||||||
use std::{boxed::Box, result};
|
use std::{boxed::Box, result};
|
||||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
|
use vm_memory::Address;
|
||||||
use vm_migration::{
|
use vm_migration::{
|
||||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable,
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable,
|
||||||
VersionMapped,
|
VersionMapped,
|
||||||
@@ -83,7 +84,7 @@ pub mod kvm {
|
|||||||
|
|
||||||
/// Get the address of the GIC distributor.
|
/// Get the address of the GIC distributor.
|
||||||
pub fn get_dist_addr() -> u64 {
|
pub fn get_dist_addr() -> u64 {
|
||||||
layout::GIC_V3_DIST_START
|
layout::GIC_V3_DIST_START.raw_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the GIC distributor.
|
/// Get the size of the GIC distributor.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
//
|
//
|
||||||
// Memory layout of Aarch64 guest:
|
// Memory layout of AArch64 guest:
|
||||||
//
|
//
|
||||||
// Physical +---------------------------------------------------------------+
|
// Physical +---------------------------------------------------------------+
|
||||||
// address | |
|
// address | |
|
||||||
@@ -20,6 +20,13 @@
|
|||||||
// | DRAM |
|
// | DRAM |
|
||||||
// | |
|
// | |
|
||||||
// | |
|
// | |
|
||||||
|
// 4GB +---------------------------------------------------------------+
|
||||||
|
// | 32-bit devices hole |
|
||||||
|
// 4GB-64M +---------------------------------------------------------------+
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// | DRAM |
|
||||||
|
// | |
|
||||||
// | |
|
// | |
|
||||||
// 1GB +---------------------------------------------------------------+
|
// 1GB +---------------------------------------------------------------+
|
||||||
// | |
|
// | |
|
||||||
@@ -35,11 +42,11 @@
|
|||||||
// | Legacy devices space |
|
// | Legacy devices space |
|
||||||
// | |
|
// | |
|
||||||
// 144 M +---------------------------------------------------------------|
|
// 144 M +---------------------------------------------------------------|
|
||||||
|
// | |
|
||||||
// | Reserved (now GIC is here) |
|
// | Reserved (now GIC is here) |
|
||||||
// 64 M +---------------------------------------------------------------+
|
|
||||||
// | |
|
|
||||||
// | UEFI space |
|
|
||||||
// | |
|
// | |
|
||||||
|
// 4 M +---------------------------------------------------------------+
|
||||||
|
// | UEFI flash |
|
||||||
// 0GB +---------------------------------------------------------------+
|
// 0GB +---------------------------------------------------------------+
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -48,17 +55,16 @@ use vm_memory::GuestAddress;
|
|||||||
|
|
||||||
/// 0x0 ~ 0x40_0000 (4 MiB) is reserved to UEFI
|
/// 0x0 ~ 0x40_0000 (4 MiB) is reserved to UEFI
|
||||||
/// UEFI binary size is required less than 3 MiB, reserving 4 MiB is enough.
|
/// UEFI binary size is required less than 3 MiB, reserving 4 MiB is enough.
|
||||||
pub const UEFI_START: u64 = 0x0;
|
pub const UEFI_START: GuestAddress = GuestAddress(0);
|
||||||
pub const MEM_UEFI_START: GuestAddress = GuestAddress(0);
|
|
||||||
pub const UEFI_SIZE: u64 = 0x040_0000;
|
pub const UEFI_SIZE: u64 = 0x040_0000;
|
||||||
|
|
||||||
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
|
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
|
||||||
pub const MAPPED_IO_START: u64 = 0x0900_0000;
|
pub const MAPPED_IO_START: GuestAddress = GuestAddress(0x0900_0000);
|
||||||
|
|
||||||
/// See kernel file arch/arm64/include/uapi/asm/kvm.h for the GIC related definitions.
|
/// See kernel file arch/arm64/include/uapi/asm/kvm.h for the GIC related definitions.
|
||||||
/// 0x08ff_0000 ~ 0x0900_0000 is reserved for GICv3 Distributor
|
/// 0x08ff_0000 ~ 0x0900_0000 is reserved for GICv3 Distributor
|
||||||
pub const GIC_V3_DIST_SIZE: u64 = 0x01_0000;
|
pub const GIC_V3_DIST_SIZE: u64 = 0x01_0000;
|
||||||
pub const GIC_V3_DIST_START: u64 = MAPPED_IO_START - GIC_V3_DIST_SIZE;
|
pub const GIC_V3_DIST_START: GuestAddress = GuestAddress(MAPPED_IO_START.0 - GIC_V3_DIST_SIZE);
|
||||||
/// Below 0x08ff_0000 is reserved for GICv3 Redistributor.
|
/// Below 0x08ff_0000 is reserved for GICv3 Redistributor.
|
||||||
/// The size defined here is for each vcpu.
|
/// The size defined here is for each vcpu.
|
||||||
/// The total size is 'number_of_vcpu * GIC_V3_REDIST_SIZE'
|
/// The total size is 'number_of_vcpu * GIC_V3_REDIST_SIZE'
|
||||||
@@ -67,9 +73,9 @@ pub const GIC_V3_REDIST_SIZE: u64 = 0x02_0000;
|
|||||||
pub const GIC_V3_ITS_SIZE: u64 = 0x02_0000;
|
pub const GIC_V3_ITS_SIZE: u64 = 0x02_0000;
|
||||||
|
|
||||||
/// Space 0x0900_0000 ~ 0x0905_0000 is reserved for legacy devices.
|
/// Space 0x0900_0000 ~ 0x0905_0000 is reserved for legacy devices.
|
||||||
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
|
pub const LEGACY_SERIAL_MAPPED_IO_START: GuestAddress = GuestAddress(0x0900_0000);
|
||||||
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
|
pub const LEGACY_RTC_MAPPED_IO_START: GuestAddress = GuestAddress(0x0901_0000);
|
||||||
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
|
pub const LEGACY_GPIO_MAPPED_IO_START: GuestAddress = GuestAddress(0x0902_0000);
|
||||||
|
|
||||||
/// Space 0x0905_0000 ~ 0x0906_0000 is reserved for pcie io address
|
/// Space 0x0905_0000 ~ 0x0906_0000 is reserved for pcie io address
|
||||||
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0905_0000);
|
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0905_0000);
|
||||||
@@ -85,8 +91,15 @@ pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
|
|||||||
// One bus with potentially 256 devices (32 slots x 8 functions).
|
// One bus with potentially 256 devices (32 slots x 8 functions).
|
||||||
pub const PCI_MMIO_CONFIG_SIZE_PER_SEGMENT: u64 = 4096 * 256;
|
pub const PCI_MMIO_CONFIG_SIZE_PER_SEGMENT: u64 = 4096 * 256;
|
||||||
|
|
||||||
/// Start of RAM on 64 bit ARM.
|
/// Start of RAM.
|
||||||
pub const RAM_64BIT_START: u64 = 0x4000_0000;
|
pub const RAM_START: GuestAddress = GuestAddress(0x4000_0000);
|
||||||
|
|
||||||
|
/// 32-bit reserved area: 64MiB before 4GiB
|
||||||
|
pub const MEM_32BIT_RESERVED_START: GuestAddress = GuestAddress(0xfc00_0000);
|
||||||
|
pub const MEM_32BIT_RESERVED_SIZE: u64 = 0x0400_0000;
|
||||||
|
|
||||||
|
/// Start of 64-bit RAM.
|
||||||
|
pub const RAM_64BIT_START: GuestAddress = GuestAddress(0x1_0000_0000);
|
||||||
|
|
||||||
/// Kernel command line maximum size.
|
/// Kernel command line maximum size.
|
||||||
/// As per `arch/arm64/include/uapi/asm/setup.h`.
|
/// As per `arch/arm64/include/uapi/asm/setup.h`.
|
||||||
@@ -94,19 +107,19 @@ pub const CMDLINE_MAX_SIZE: usize = 2048;
|
|||||||
|
|
||||||
/// FDT is at the beginning of RAM.
|
/// FDT is at the beginning of RAM.
|
||||||
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
|
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
|
||||||
pub const FDT_START: u64 = RAM_64BIT_START;
|
pub const FDT_START: GuestAddress = RAM_START;
|
||||||
pub const FDT_MAX_SIZE: usize = 0x20_0000;
|
pub const FDT_MAX_SIZE: u64 = 0x20_0000;
|
||||||
|
|
||||||
/// Put ACPI table above dtb
|
/// Put ACPI table above dtb
|
||||||
pub const ACPI_START: u64 = RAM_64BIT_START + FDT_MAX_SIZE as u64;
|
pub const ACPI_START: GuestAddress = GuestAddress(RAM_START.0 + FDT_MAX_SIZE);
|
||||||
pub const ACPI_MAX_SIZE: usize = 0x20_0000;
|
pub const ACPI_MAX_SIZE: u64 = 0x20_0000;
|
||||||
pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START);
|
pub const RSDP_POINTER: GuestAddress = ACPI_START;
|
||||||
|
|
||||||
/// Kernel start after FDT and ACPI
|
/// Kernel start after FDT and ACPI
|
||||||
pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
|
pub const KERNEL_START: GuestAddress = GuestAddress(ACPI_START.0 + ACPI_MAX_SIZE);
|
||||||
|
|
||||||
/// Pci high memory base
|
/// Pci high memory base
|
||||||
pub const PCI_HIGH_BASE: u64 = 0x2_0000_0000_u64;
|
pub const PCI_HIGH_BASE: GuestAddress = GuestAddress(0x2_0000_0000);
|
||||||
|
|
||||||
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
||||||
// the number of interrupts our GIC will support to be:
|
// the number of interrupts our GIC will support to be:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub enum Error {
|
|||||||
|
|
||||||
impl From<Error> for super::Error {
|
impl From<Error> for super::Error {
|
||||||
fn from(e: Error) -> super::Error {
|
fn from(e: Error) -> super::Error {
|
||||||
super::Error::AArch64Setup(e)
|
super::Error::PlatformSpecific(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,45 +64,25 @@ pub struct EntryPoint {
|
|||||||
|
|
||||||
/// Configure the specified VCPU, and return its MPIDR.
|
/// Configure the specified VCPU, and return its MPIDR.
|
||||||
pub fn configure_vcpu(
|
pub fn configure_vcpu(
|
||||||
fd: &Arc<dyn hypervisor::Vcpu>,
|
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
||||||
id: u8,
|
id: u8,
|
||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
) -> super::Result<u64> {
|
) -> super::Result<u64> {
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
regs::setup_regs(fd, id, kernel_entry_point.entry_addr.raw_value())
|
regs::setup_regs(vcpu, id, kernel_entry_point.entry_addr.raw_value())
|
||||||
.map_err(Error::RegsConfiguration)?;
|
.map_err(Error::RegsConfiguration)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mpidr = fd.read_mpidr().map_err(Error::VcpuRegMpidr)?;
|
let mpidr = vcpu.read_mpidr().map_err(Error::VcpuRegMpidr)?;
|
||||||
Ok(mpidr)
|
Ok(mpidr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||||
// Normally UEFI should be loaded to a flash area at the beginning of memory.
|
let mut regions = vec![
|
||||||
// But now flash memory type is not supported.
|
// 0 MiB ~ 256 MiB: UEFI, GIC and legacy devices
|
||||||
// As a workaround, we take 4 MiB memory from the main RAM for UEFI.
|
|
||||||
// As a result, the RAM that the guest can see is less than what has been
|
|
||||||
// assigned in command line, when ACPI and UEFI is enabled.
|
|
||||||
let ram_deduction = if cfg!(feature = "acpi") {
|
|
||||||
layout::UEFI_SIZE
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
vec![
|
|
||||||
// 0 ~ 4 MiB: Reserved for UEFI space
|
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
(GuestAddress(0), layout::UEFI_SIZE as usize, RegionType::Ram),
|
|
||||||
#[cfg(not(feature = "acpi"))]
|
|
||||||
(
|
(
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
layout::UEFI_SIZE as usize,
|
layout::MEM_32BIT_DEVICES_START.0 as usize,
|
||||||
RegionType::Reserved,
|
|
||||||
),
|
|
||||||
// 4 MiB ~ 256 MiB: Gic and legacy devices
|
|
||||||
(
|
|
||||||
GuestAddress(layout::UEFI_SIZE),
|
|
||||||
(layout::MEM_32BIT_DEVICES_START.0 - layout::UEFI_SIZE) as usize,
|
|
||||||
RegionType::Reserved,
|
RegionType::Reserved,
|
||||||
),
|
),
|
||||||
// 256 MiB ~ 768 MiB: MMIO space
|
// 256 MiB ~ 768 MiB: MMIO space
|
||||||
@@ -117,13 +97,39 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
|
|||||||
layout::PCI_MMCONFIG_SIZE as usize,
|
layout::PCI_MMCONFIG_SIZE as usize,
|
||||||
RegionType::Reserved,
|
RegionType::Reserved,
|
||||||
),
|
),
|
||||||
// 1 GiB ~ : Ram
|
];
|
||||||
(
|
|
||||||
GuestAddress(layout::RAM_64BIT_START),
|
let ram_32bit_space_size =
|
||||||
(size - ram_deduction) as usize,
|
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START);
|
||||||
|
|
||||||
|
// RAM space
|
||||||
|
// Case1: guest memory fits before the gap
|
||||||
|
if size as u64 <= ram_32bit_space_size {
|
||||||
|
regions.push((layout::RAM_START, size as usize, RegionType::Ram));
|
||||||
|
// Case2: guest memory extends beyond the gap
|
||||||
|
} else {
|
||||||
|
// Push memory before the gap
|
||||||
|
regions.push((
|
||||||
|
layout::RAM_START,
|
||||||
|
ram_32bit_space_size as usize,
|
||||||
RegionType::Ram,
|
RegionType::Ram,
|
||||||
),
|
));
|
||||||
]
|
// Other memory is placed after 4GiB
|
||||||
|
regions.push((
|
||||||
|
layout::RAM_64BIT_START,
|
||||||
|
(size - ram_32bit_space_size) as usize,
|
||||||
|
RegionType::Ram,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the 32-bit reserved memory hole as a reserved region
|
||||||
|
regions.push((
|
||||||
|
layout::MEM_32BIT_RESERVED_START,
|
||||||
|
layout::MEM_32BIT_RESERVED_SIZE as usize,
|
||||||
|
RegionType::Reserved,
|
||||||
|
));
|
||||||
|
|
||||||
|
regions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||||
@@ -179,28 +185,13 @@ pub fn initramfs_load_addr(
|
|||||||
if guest_mem.address_in_range(offset) {
|
if guest_mem.address_in_range(offset) {
|
||||||
Ok(offset.raw_value())
|
Ok(offset.raw_value())
|
||||||
} else {
|
} else {
|
||||||
Err(super::Error::AArch64Setup(Error::InitramfsAddress))
|
Err(super::Error::PlatformSpecific(Error::InitramfsAddress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Err(super::Error::AArch64Setup(Error::InitramfsAddress)),
|
None => Err(super::Error::PlatformSpecific(Error::InitramfsAddress)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the memory address where the kernel could be loaded.
|
|
||||||
pub fn get_kernel_start() -> u64 {
|
|
||||||
layout::KERNEL_START
|
|
||||||
}
|
|
||||||
|
|
||||||
///Return guest memory address where the uefi should be loaded.
|
|
||||||
pub fn get_uefi_start() -> u64 {
|
|
||||||
layout::UEFI_START
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auxiliary function to get the address where the device tree blob is loaded.
|
|
||||||
fn get_fdt_addr() -> u64 {
|
|
||||||
layout::FDT_START
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_host_cpu_phys_bits() -> u8 {
|
pub fn get_host_cpu_phys_bits() -> u8 {
|
||||||
// A dummy hypervisor created only for querying the host IPA size and will
|
// A dummy hypervisor created only for querying the host IPA size and will
|
||||||
// be freed after the query.
|
// be freed after the query.
|
||||||
@@ -220,11 +211,26 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arch_memory_regions_dram() {
|
fn test_arch_memory_regions_dram_2gb() {
|
||||||
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
let regions = arch_memory_regions((1usize << 31) as u64); //2GB
|
||||||
assert_eq!(5, regions.len());
|
assert_eq!(5, regions.len());
|
||||||
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[4].0);
|
assert_eq!(layout::RAM_START, regions[3].0);
|
||||||
assert_eq!(1usize << 32, regions[4].1);
|
assert_eq!((1usize << 31), regions[3].1);
|
||||||
|
assert_eq!(RegionType::Ram, regions[3].2);
|
||||||
|
assert_eq!(RegionType::Reserved, regions[4].2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arch_memory_regions_dram_4gb() {
|
||||||
|
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
||||||
|
let ram_32bit_space_size =
|
||||||
|
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize;
|
||||||
|
assert_eq!(6, regions.len());
|
||||||
|
assert_eq!(layout::RAM_START, regions[3].0);
|
||||||
|
assert_eq!(ram_32bit_space_size as usize, regions[3].1);
|
||||||
|
assert_eq!(RegionType::Ram, regions[3].2);
|
||||||
|
assert_eq!(RegionType::Reserved, regions[5].2);
|
||||||
assert_eq!(RegionType::Ram, regions[4].2);
|
assert_eq!(RegionType::Ram, regions[4].2);
|
||||||
|
assert_eq!(((1usize << 32) - ram_32bit_space_size), regions[4].1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use super::get_fdt_addr;
|
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
use hypervisor::kvm::kvm_bindings::{
|
||||||
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||||
};
|
};
|
||||||
use hypervisor::{arm64_core_reg_id, offset__of};
|
use hypervisor::{arm64_core_reg_id, offset__of};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{mem, result};
|
use std::{mem, result};
|
||||||
|
use vm_memory::Address;
|
||||||
|
|
||||||
/// Errors thrown while setting aarch64 registers.
|
/// Errors thrown while setting aarch64 registers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -67,7 +67,7 @@ pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, cpu_id: u8, boot_ip: u64) ->
|
|||||||
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
|
||||||
vcpu.set_reg(
|
vcpu.set_reg(
|
||||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
||||||
get_fdt_addr() as u64,
|
super::layout::FDT_START.raw_value(),
|
||||||
)
|
)
|
||||||
.map_err(Error::SetCoreRegister)?;
|
.map_err(Error::SetCoreRegister)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,15 @@
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::x86_64::SgxEpcSection;
|
use crate::x86_64::SgxEpcSection;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use thiserror::Error;
|
||||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
use vm_migration::VersionMapped;
|
use vm_migration::VersionMapped;
|
||||||
@@ -26,31 +26,27 @@ type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitma
|
|||||||
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
|
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||||
|
|
||||||
/// Type for returning error code.
|
/// Type for returning error code.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
/// X86_64 specific error triggered during system configuration.
|
#[error("Platform specific error (x86_64): {0:?}")]
|
||||||
X86_64Setup(x86_64::Error),
|
PlatformSpecific(x86_64::Error),
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
/// AArch64 specific error triggered during system configuration.
|
#[error("Platform specific error (aarch64): {0:?}")]
|
||||||
AArch64Setup(aarch64::Error),
|
PlatformSpecific(aarch64::Error),
|
||||||
/// The zero page extends past the end of guest_mem.
|
#[error("The memory map table extends past the end of guest memory")]
|
||||||
ZeroPagePastRamEnd,
|
|
||||||
/// Error writing the zero page of guest memory.
|
|
||||||
ZeroPageSetup(vm_memory::GuestMemoryError),
|
|
||||||
/// The memory map table extends past the end of guest memory.
|
|
||||||
MemmapTablePastRamEnd,
|
MemmapTablePastRamEnd,
|
||||||
/// Error writing memory map table to guest memory.
|
#[error("Error writing memory map table to guest memory")]
|
||||||
MemmapTableSetup,
|
MemmapTableSetup,
|
||||||
/// The hvm_start_info structure extends past the end of guest memory.
|
#[error("The hvm_start_info structure extends past the end of guest memory")]
|
||||||
StartInfoPastRamEnd,
|
StartInfoPastRamEnd,
|
||||||
/// Error writing hvm_start_info to guest memory.
|
#[error("Error writing hvm_start_info to guest memory")]
|
||||||
StartInfoSetup,
|
StartInfoSetup,
|
||||||
/// Failed to compute initramfs address.
|
#[error("Failed to compute initramfs address")]
|
||||||
InitramfsAddress,
|
InitramfsAddress,
|
||||||
/// Error writing module entry to guest memory.
|
#[error("Error writing module entry to guest memory: {0}")]
|
||||||
ModlistSetup(vm_memory::GuestMemoryError),
|
ModlistSetup(#[source] vm_memory::GuestMemoryError),
|
||||||
/// RSDP Beyond Guest Memory
|
#[error("RSDP extends past the end of guest memory")]
|
||||||
RsdpPastRamEnd,
|
RsdpPastRamEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +81,8 @@ pub mod aarch64;
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub use aarch64::{
|
pub use aarch64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
|
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
|
||||||
get_host_cpu_phys_bits, get_kernel_start, get_uefi_start, initramfs_load_addr, layout,
|
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||||
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, uefi, EntryPoint,
|
layout::IRQ_BASE, uefi, EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -158,6 +154,7 @@ impl fmt::Display for DeviceType {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub struct MmioDeviceInfo {
|
pub struct MmioDeviceInfo {
|
||||||
pub addr: u64,
|
pub addr: u64,
|
||||||
|
pub len: u64,
|
||||||
pub irq: u32,
|
pub irq: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +177,6 @@ impl DeviceInfoForFdt for MmioDeviceInfo {
|
|||||||
self.irq
|
self.irq
|
||||||
}
|
}
|
||||||
fn length(&self) -> u64 {
|
fn length(&self) -> u64 {
|
||||||
4096
|
self.len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ pub const LOW_RAM_START: GuestAddress = GuestAddress(0x0);
|
|||||||
|
|
||||||
// == Fixed addresses within the "Low RAM" range: ==
|
// == Fixed addresses within the "Low RAM" range: ==
|
||||||
|
|
||||||
|
// Location of EBDA address
|
||||||
|
pub const EBDA_POINTER: GuestAddress = GuestAddress(0x40e);
|
||||||
|
|
||||||
// Initial GDT/IDT needed to boot kernel
|
// Initial GDT/IDT needed to boot kernel
|
||||||
pub const BOOT_GDT_START: GuestAddress = GuestAddress(0x500);
|
pub const BOOT_GDT_START: GuestAddress = GuestAddress(0x500);
|
||||||
pub const BOOT_IDT_START: GuestAddress = GuestAddress(0x520);
|
pub const BOOT_IDT_START: GuestAddress = GuestAddress(0x520);
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ pub mod regs;
|
|||||||
use crate::GuestMemoryMmap;
|
use crate::GuestMemoryMmap;
|
||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use hypervisor::{CpuId, CpuIdEntry, HypervisorError, CPUID_FLAG_VALID_INDEX};
|
use hypervisor::x86_64::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
||||||
|
use hypervisor::HypervisorError;
|
||||||
use linux_loader::loader::bootparam::boot_params;
|
use linux_loader::loader::bootparam::boot_params;
|
||||||
use linux_loader::loader::elf::start_info::{
|
use linux_loader::loader::elf::start_info::{
|
||||||
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
||||||
@@ -186,11 +187,18 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Error checking CPUID compatibility
|
/// Error checking CPUID compatibility
|
||||||
CpuidCheckCompatibility,
|
CpuidCheckCompatibility,
|
||||||
|
|
||||||
|
// Error writing EBDA address
|
||||||
|
EbdaSetup(vm_memory::GuestMemoryError),
|
||||||
|
|
||||||
|
/// Error retrieving TDX capabilities through the hypervisor (kvm/mshv) API
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
TdxCapabilities(HypervisorError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for super::Error {
|
impl From<Error> for super::Error {
|
||||||
fn from(e: Error) -> super::Error {
|
fn from(e: Error) -> super::Error {
|
||||||
super::Error::X86_64Setup(e)
|
super::Error::PlatformSpecific(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,9 +605,39 @@ pub fn generate_common_cpuid(
|
|||||||
update_cpuid_sgx(&mut cpuid, sgx_epc_sections)?;
|
update_cpuid_sgx(&mut cpuid, sgx_epc_sections)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
let tdx_capabilities = if tdx_enabled {
|
||||||
|
let caps = hypervisor
|
||||||
|
.tdx_capabilities()
|
||||||
|
.map_err(Error::TdxCapabilities)?;
|
||||||
|
info!("TDX capabilities {:#?}", caps);
|
||||||
|
Some(caps)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Update some existing CPUID
|
// Update some existing CPUID
|
||||||
for entry in cpuid.as_mut_slice().iter_mut() {
|
for entry in cpuid.as_mut_slice().iter_mut() {
|
||||||
match entry.function {
|
match entry.function {
|
||||||
|
0xd =>
|
||||||
|
{
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
if let Some(caps) = &tdx_capabilities {
|
||||||
|
let xcr0_mask: u64 = 0x82ff;
|
||||||
|
let xss_mask: u64 = !xcr0_mask;
|
||||||
|
if entry.index == 0 {
|
||||||
|
entry.eax &= (caps.xfam_fixed0 as u32) & (xcr0_mask as u32);
|
||||||
|
entry.eax |= (caps.xfam_fixed1 as u32) & (xcr0_mask as u32);
|
||||||
|
entry.edx &= ((caps.xfam_fixed0 & xcr0_mask) >> 32) as u32;
|
||||||
|
entry.edx |= ((caps.xfam_fixed1 & xcr0_mask) >> 32) as u32;
|
||||||
|
} else if entry.index == 1 {
|
||||||
|
entry.ecx &= (caps.xfam_fixed0 as u32) & (xss_mask as u32);
|
||||||
|
entry.ecx |= (caps.xfam_fixed1 as u32) & (xss_mask as u32);
|
||||||
|
entry.edx &= ((caps.xfam_fixed0 & xss_mask) >> 32) as u32;
|
||||||
|
entry.edx |= ((caps.xfam_fixed1 & xss_mask) >> 32) as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Set CPU physical bits
|
// Set CPU physical bits
|
||||||
0x8000_0008 => {
|
0x8000_0008 => {
|
||||||
entry.eax = (entry.eax & 0xffff_ff00) | (phys_bits as u32 & 0xff);
|
entry.eax = (entry.eax & 0xffff_ff00) | (phys_bits as u32 & 0xff);
|
||||||
@@ -706,7 +744,7 @@ pub fn generate_common_cpuid(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_vcpu(
|
pub fn configure_vcpu(
|
||||||
fd: &Arc<dyn hypervisor::Vcpu>,
|
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
||||||
id: u8,
|
id: u8,
|
||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
@@ -718,23 +756,23 @@ pub fn configure_vcpu(
|
|||||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
||||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
|
||||||
|
|
||||||
fd.set_cpuid2(&cpuid)
|
vcpu.set_cpuid2(&cpuid)
|
||||||
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
|
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
|
||||||
|
|
||||||
if kvm_hyperv {
|
if kvm_hyperv {
|
||||||
fd.enable_hyperv_synic().unwrap();
|
vcpu.enable_hyperv_synic().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
regs::setup_msrs(vcpu).map_err(Error::MsrsConfiguration)?;
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
if let Some(entry_addr) = kernel_entry_point.entry_addr {
|
if let Some(entry_addr) = kernel_entry_point.entry_addr {
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
regs::setup_regs(fd, entry_addr.raw_value()).map_err(Error::RegsConfiguration)?;
|
regs::setup_regs(vcpu, entry_addr.raw_value()).map_err(Error::RegsConfiguration)?;
|
||||||
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
||||||
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
|
regs::setup_sregs(&vm_memory.memory(), vcpu).map_err(Error::SregsConfiguration)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
interrupts::set_lint(vcpu).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,8 +839,14 @@ pub fn configure_system(
|
|||||||
_num_cpus: u8,
|
_num_cpus: u8,
|
||||||
rsdp_addr: Option<GuestAddress>,
|
rsdp_addr: Option<GuestAddress>,
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
sgx_epc_region: Option<SgxEpcRegion>,
|
||||||
|
serial_number: Option<&str>,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
|
// Write EBDA address to location where ACPICA expects to find it
|
||||||
|
guest_mem
|
||||||
|
.write_obj((layout::EBDA_START.0 >> 4) as u16, layout::EBDA_POINTER)
|
||||||
|
.map_err(Error::EbdaSetup)?;
|
||||||
|
|
||||||
|
let size = smbios::setup_smbios(guest_mem, serial_number).map_err(Error::SmbiosSetup)?;
|
||||||
|
|
||||||
// Place the MP table after the SMIOS table aligned to 16 bytes
|
// Place the MP table after the SMIOS table aligned to 16 bytes
|
||||||
let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size);
|
let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size);
|
||||||
@@ -1151,6 +1195,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
Some(layout::RSDP_POINTER),
|
Some(layout::RSDP_POINTER),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
assert!(config_err.is_err());
|
assert!(config_err.is_err());
|
||||||
|
|
||||||
@@ -1164,7 +1209,7 @@ mod tests {
|
|||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
|
|
||||||
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap();
|
||||||
|
|
||||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
||||||
let mem_size = 3328 << 20;
|
let mem_size = 3328 << 20;
|
||||||
@@ -1175,9 +1220,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap();
|
||||||
|
|
||||||
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap();
|
||||||
|
|
||||||
// Now assigning some memory that falls after the 32bit memory hole.
|
// Now assigning some memory that falls after the 32bit memory hole.
|
||||||
let mem_size = 3330 << 20;
|
let mem_size = 3330 << 20;
|
||||||
@@ -1188,9 +1233,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap();
|
||||||
|
|
||||||
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
|
use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
|
||||||
use crate::GuestMemoryMmap;
|
use crate::GuestMemoryMmap;
|
||||||
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
||||||
use hypervisor::arch::x86::regs::*;
|
use hypervisor::arch::x86::regs::CR0_PE;
|
||||||
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{mem, result};
|
use std::{mem, result};
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ fn write_string(
|
|||||||
Ok(curptr)
|
Ok(curptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<u64> {
|
pub fn setup_smbios(mem: &GuestMemoryMmap, serial_number: Option<&str>) -> Result<u64> {
|
||||||
let physptr = GuestAddress(SMBIOS_START)
|
let physptr = GuestAddress(SMBIOS_START)
|
||||||
.checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
|
.checked_add(mem::size_of::<Smbios30Entrypoint>() as u64)
|
||||||
.ok_or(Error::NotEnoughMemory)?;
|
.ok_or(Error::NotEnoughMemory)?;
|
||||||
@@ -195,11 +195,15 @@ pub fn setup_smbios(mem: &GuestMemoryMmap) -> Result<u64> {
|
|||||||
handle,
|
handle,
|
||||||
manufacturer: 1, // First string written in this section
|
manufacturer: 1, // First string written in this section
|
||||||
product_name: 2, // Second string written in this section
|
product_name: 2, // Second string written in this section
|
||||||
|
serial_number: serial_number.map(|_| 3).unwrap_or_default(), // 3rd string
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
|
curptr = write_and_incr(mem, smbios_sysinfo, curptr)?;
|
||||||
curptr = write_string(mem, "Cloud Hypervisor", curptr)?;
|
curptr = write_string(mem, "Cloud Hypervisor", curptr)?;
|
||||||
curptr = write_string(mem, "cloud-hypervisor", curptr)?;
|
curptr = write_string(mem, "cloud-hypervisor", curptr)?;
|
||||||
|
if let Some(serial_number) = serial_number {
|
||||||
|
curptr = write_string(mem, serial_number, curptr)?;
|
||||||
|
}
|
||||||
curptr = write_and_incr(mem, 0u8, curptr)?;
|
curptr = write_and_incr(mem, 0u8, curptr)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +267,7 @@ mod tests {
|
|||||||
fn entrypoint_checksum() {
|
fn entrypoint_checksum() {
|
||||||
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(SMBIOS_START), 4096)]).unwrap();
|
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(SMBIOS_START), 4096)]).unwrap();
|
||||||
|
|
||||||
setup_smbios(&mem).unwrap();
|
setup_smbios(&mem, None).unwrap();
|
||||||
|
|
||||||
let smbios_ep: Smbios30Entrypoint = mem.read_obj(GuestAddress(SMBIOS_START)).unwrap();
|
let smbios_ep: Smbios30Entrypoint = mem.read_obj(GuestAddress(SMBIOS_START)).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -324,10 +324,10 @@ impl TdHob {
|
|||||||
},
|
},
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* QEMU currently fills it in like this:
|
* QEMU currently fills it in like this:
|
||||||
* EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_ENCRYPTED | EFI_RESOURCE_ATTRIBUTE_TESTED
|
* EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED
|
||||||
* which differs from the spec (due to TDVF implementation issue?)
|
* which differs from the spec (due to TDVF implementation issue?)
|
||||||
*/
|
*/
|
||||||
0x04000007,
|
0x7,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,23 +2,23 @@
|
|||||||
name = "block_util"
|
name = "block_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
io-uring = "0.5.2"
|
io-uring = "0.5.2"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.31"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vhdx = { path = "../vhdx" }
|
vhdx = { path = "../vhdx" }
|
||||||
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
|
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
|
||||||
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio", branch = "main" }
|
virtio-queue = "0.3.0"
|
||||||
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.8.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ impl Request {
|
|||||||
|
|
||||||
let hdr_desc_addr = hdr_desc
|
let hdr_desc_addr = hdr_desc
|
||||||
.addr()
|
.addr()
|
||||||
.translate(access_platform, hdr_desc.len() as usize);
|
.translate_gva(access_platform, hdr_desc.len() as usize);
|
||||||
|
|
||||||
let mut req = Request {
|
let mut req = Request {
|
||||||
request_type: request_type(desc_chain.memory(), hdr_desc_addr)?,
|
request_type: request_type(desc_chain.memory(), hdr_desc_addr)?,
|
||||||
@@ -249,7 +249,8 @@ impl Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.data_descriptors.push((
|
req.data_descriptors.push((
|
||||||
desc.addr().translate(access_platform, desc.len() as usize),
|
desc.addr()
|
||||||
|
.translate_gva(access_platform, desc.len() as usize),
|
||||||
desc.len(),
|
desc.len(),
|
||||||
));
|
));
|
||||||
desc = desc_chain
|
desc = desc_chain
|
||||||
@@ -274,7 +275,7 @@ impl Request {
|
|||||||
|
|
||||||
req.status_addr = status_desc
|
req.status_addr = status_desc
|
||||||
.addr()
|
.addr()
|
||||||
.translate(access_platform, status_desc.len() as usize);
|
.translate_gva(access_platform, status_desc.len() as usize);
|
||||||
|
|
||||||
Ok(req)
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,25 @@
|
|||||||
name = "devices"
|
name = "devices"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables" }
|
||||||
anyhow = "1.0.55"
|
anyhow = "1.0.57"
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
bitflags = "1.3.2"
|
bitflags = "1.3.2"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.7.0"
|
vm-memory = "0.8.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
acpi = ["acpi_tables"]
|
|
||||||
cmos = []
|
cmos = []
|
||||||
fwdebug = []
|
fwdebug = []
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ impl BusDevice for AcpiGedDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
impl Aml for AcpiGedDevice {
|
impl Aml for AcpiGedDevice {
|
||||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
aml::Device::new(
|
aml::Device::new(
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ impl InterruptController for Gic {
|
|||||||
.update(
|
.update(
|
||||||
i as InterruptIndex,
|
i as InterruptIndex,
|
||||||
InterruptSourceConfig::LegacyIrq(config),
|
InterruptSourceConfig::LegacyIrq(config),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.map_err(Error::EnableInterrupt)?;
|
.map_err(Error::EnableInterrupt)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,19 +367,13 @@ impl Ioapic {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
.update(irq as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
.update(
|
||||||
|
irq as InterruptIndex,
|
||||||
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
interrupt_mask(entry) == 1,
|
||||||
|
)
|
||||||
.map_err(Error::UpdateInterrupt)?;
|
.map_err(Error::UpdateInterrupt)?;
|
||||||
|
|
||||||
if interrupt_mask(entry) == 1 {
|
|
||||||
self.interrupt_source_group
|
|
||||||
.mask(irq as InterruptIndex)
|
|
||||||
.map_err(Error::MaskInterrupt)?;
|
|
||||||
} else {
|
|
||||||
self.interrupt_source_group
|
|
||||||
.unmask(irq as InterruptIndex)
|
|
||||||
.map_err(Error::UnmaskInterrupt)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use std::cmp::min;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
// https://github.com/rust-lang/libc/issues/1848
|
// https://github.com/rust-lang/libc/issues/1848
|
||||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||||
@@ -21,13 +22,14 @@ const DATA_LEN: usize = 128;
|
|||||||
pub struct Cmos {
|
pub struct Cmos {
|
||||||
index: u8,
|
index: u8,
|
||||||
data: [u8; DATA_LEN],
|
data: [u8; DATA_LEN],
|
||||||
|
reset_evt: EventFd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cmos {
|
impl Cmos {
|
||||||
/// Constructs a CMOS/RTC device with initial data.
|
/// Constructs a CMOS/RTC device with initial data.
|
||||||
/// `mem_below_4g` is the size of memory in bytes below the 32-bit gap.
|
/// `mem_below_4g` is the size of memory in bytes below the 32-bit gap.
|
||||||
/// `mem_above_4g` is the size of memory in bytes above the 32-bit gap.
|
/// `mem_above_4g` is the size of memory in bytes above the 32-bit gap.
|
||||||
pub fn new(mem_below_4g: u64, mem_above_4g: u64) -> Cmos {
|
pub fn new(mem_below_4g: u64, mem_above_4g: u64, reset_evt: EventFd) -> Cmos {
|
||||||
let mut data = [0u8; DATA_LEN];
|
let mut data = [0u8; DATA_LEN];
|
||||||
|
|
||||||
// Extended memory from 16 MB to 4 GB in units of 64 KB
|
// Extended memory from 16 MB to 4 GB in units of 64 KB
|
||||||
@@ -44,7 +46,11 @@ impl Cmos {
|
|||||||
data[0x5c] = (high_mem >> 8) as u8;
|
data[0x5c] = (high_mem >> 8) as u8;
|
||||||
data[0x5d] = (high_mem >> 16) as u8;
|
data[0x5d] = (high_mem >> 16) as u8;
|
||||||
|
|
||||||
Cmos { index: 0, data }
|
Cmos {
|
||||||
|
index: 0,
|
||||||
|
data,
|
||||||
|
reset_evt,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +62,15 @@ impl BusDevice for Cmos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match offset {
|
match offset {
|
||||||
INDEX_OFFSET => self.index = data[0] & INDEX_MASK,
|
INDEX_OFFSET => self.index = data[0],
|
||||||
DATA_OFFSET => self.data[self.index as usize] = data[0],
|
DATA_OFFSET => {
|
||||||
|
if self.index == 0x8f && data[0] == 0 {
|
||||||
|
info!("CMOS reset");
|
||||||
|
self.reset_evt.write(1).unwrap();
|
||||||
|
} else {
|
||||||
|
self.data[(self.index & INDEX_MASK) as usize] = data[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
o => warn!("bad write offset on CMOS device: {}", o),
|
o => warn!("bad write offset on CMOS device: {}", o),
|
||||||
};
|
};
|
||||||
None
|
None
|
||||||
|
|||||||
86
devices/src/legacy/debug_port.rs
Normal file
86
devices/src/legacy/debug_port.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Copyright © 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::time::Instant;
|
||||||
|
use vm_device::BusDevice;
|
||||||
|
|
||||||
|
/// Debug I/O port, see:
|
||||||
|
/// https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html
|
||||||
|
///
|
||||||
|
/// Since we're not a physical platform, we can freely assign code ranges for
|
||||||
|
/// debugging specific parts of our virtual platform.
|
||||||
|
pub enum DebugIoPortRange {
|
||||||
|
Firmware,
|
||||||
|
Bootloader,
|
||||||
|
Kernel,
|
||||||
|
Userspace,
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
const DEBUG_IOPORT_PREFIX: &str = "Debug I/O port";
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
impl DebugIoPortRange {
|
||||||
|
fn from_u8(value: u8) -> DebugIoPortRange {
|
||||||
|
match value {
|
||||||
|
0x00..=0x1f => DebugIoPortRange::Firmware,
|
||||||
|
0x20..=0x3f => DebugIoPortRange::Bootloader,
|
||||||
|
0x40..=0x5f => DebugIoPortRange::Kernel,
|
||||||
|
0x60..=0x7f => DebugIoPortRange::Userspace,
|
||||||
|
_ => DebugIoPortRange::Custom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
impl fmt::Display for DebugIoPortRange {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DebugIoPortRange::Firmware => write!(f, "{}: Firmware", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Bootloader => write!(f, "{}: Bootloader", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Kernel => write!(f, "{}: Kernel", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Userspace => write!(f, "{}: Userspace", DEBUG_IOPORT_PREFIX),
|
||||||
|
DebugIoPortRange::Custom => write!(f, "{}: Custom", DEBUG_IOPORT_PREFIX),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DebugPort {
|
||||||
|
timestamp: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugPort {
|
||||||
|
pub fn new(timestamp: Instant) -> Self {
|
||||||
|
Self { timestamp }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BusDevice for DebugPort {
|
||||||
|
fn read(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {
|
||||||
|
error!("Invalid read to debug port")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(
|
||||||
|
&mut self,
|
||||||
|
_base: u64,
|
||||||
|
_offset: u64,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<std::sync::Arc<std::sync::Barrier>> {
|
||||||
|
let elapsed = self.timestamp.elapsed();
|
||||||
|
|
||||||
|
let code = data[0];
|
||||||
|
warn!(
|
||||||
|
"[{} code 0x{:x}] {}.{:>06} seconds",
|
||||||
|
DebugIoPortRange::from_u8(code),
|
||||||
|
code,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -356,6 +356,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
#[cfg(feature = "cmos")]
|
|
||||||
mod cmos;
|
mod cmos;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
mod debug_port;
|
||||||
#[cfg(feature = "fwdebug")]
|
#[cfg(feature = "fwdebug")]
|
||||||
mod fwdebug;
|
mod fwdebug;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@@ -18,8 +19,9 @@ mod serial;
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
mod uart_pl011;
|
mod uart_pl011;
|
||||||
|
|
||||||
#[cfg(feature = "cmos")]
|
|
||||||
pub use self::cmos::Cmos;
|
pub use self::cmos::Cmos;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub use self::debug_port::DebugPort;
|
||||||
#[cfg(feature = "fwdebug")]
|
#[cfg(feature = "fwdebug")]
|
||||||
pub use self::fwdebug::FwDebugDevice;
|
pub use self::fwdebug::FwDebugDevice;
|
||||||
pub use self::i8042::I8042Device;
|
pub use self::i8042::I8042Device;
|
||||||
|
|||||||
@@ -430,6 +430,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::{read_le_u32, write_le_u32};
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
|
use std::time::Instant;
|
||||||
use std::{io, result};
|
use std::{io, result};
|
||||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
@@ -34,6 +35,7 @@ const UARTRIS: u64 = 15;
|
|||||||
const UARTMIS: u64 = 16;
|
const UARTMIS: u64 = 16;
|
||||||
const UARTICR: u64 = 17;
|
const UARTICR: u64 = 17;
|
||||||
const UARTDMACR: u64 = 18;
|
const UARTDMACR: u64 = 18;
|
||||||
|
const UARTDEBUG: u64 = 0x3c0;
|
||||||
|
|
||||||
const PL011_INT_TX: u32 = 0x20;
|
const PL011_INT_TX: u32 = 0x20;
|
||||||
const PL011_INT_RX: u32 = 0x10;
|
const PL011_INT_RX: u32 = 0x10;
|
||||||
@@ -77,6 +79,7 @@ pub struct Pl011 {
|
|||||||
rsr: u32,
|
rsr: u32,
|
||||||
cr: u32,
|
cr: u32,
|
||||||
dmacr: u32,
|
dmacr: u32,
|
||||||
|
debug: u32,
|
||||||
int_enabled: u32,
|
int_enabled: u32,
|
||||||
int_level: u32,
|
int_level: u32,
|
||||||
read_fifo: VecDeque<u8>,
|
read_fifo: VecDeque<u8>,
|
||||||
@@ -88,6 +91,7 @@ pub struct Pl011 {
|
|||||||
read_trigger: u32,
|
read_trigger: u32,
|
||||||
irq: Arc<dyn InterruptSourceGroup>,
|
irq: Arc<dyn InterruptSourceGroup>,
|
||||||
out: Option<Box<dyn io::Write + Send>>,
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
|
timestamp: std::time::Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Versionize)]
|
#[derive(Versionize)]
|
||||||
@@ -97,6 +101,7 @@ pub struct Pl011State {
|
|||||||
rsr: u32,
|
rsr: u32,
|
||||||
cr: u32,
|
cr: u32,
|
||||||
dmacr: u32,
|
dmacr: u32,
|
||||||
|
debug: u32,
|
||||||
int_enabled: u32,
|
int_enabled: u32,
|
||||||
int_level: u32,
|
int_level: u32,
|
||||||
read_fifo: Vec<u8>,
|
read_fifo: Vec<u8>,
|
||||||
@@ -116,6 +121,7 @@ impl Pl011 {
|
|||||||
id: String,
|
id: String,
|
||||||
irq: Arc<dyn InterruptSourceGroup>,
|
irq: Arc<dyn InterruptSourceGroup>,
|
||||||
out: Option<Box<dyn io::Write + Send>>,
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
|
timestamp: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
@@ -124,6 +130,7 @@ impl Pl011 {
|
|||||||
rsr: 0u32,
|
rsr: 0u32,
|
||||||
cr: 0x300u32,
|
cr: 0x300u32,
|
||||||
dmacr: 0u32,
|
dmacr: 0u32,
|
||||||
|
debug: 0u32,
|
||||||
int_enabled: 0u32,
|
int_enabled: 0u32,
|
||||||
int_level: 0u32,
|
int_level: 0u32,
|
||||||
read_fifo: VecDeque::new(),
|
read_fifo: VecDeque::new(),
|
||||||
@@ -135,6 +142,7 @@ impl Pl011 {
|
|||||||
read_trigger: 1u32,
|
read_trigger: 1u32,
|
||||||
irq,
|
irq,
|
||||||
out,
|
out,
|
||||||
|
timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +157,7 @@ impl Pl011 {
|
|||||||
rsr: self.rsr,
|
rsr: self.rsr,
|
||||||
cr: self.cr,
|
cr: self.cr,
|
||||||
dmacr: self.dmacr,
|
dmacr: self.dmacr,
|
||||||
|
debug: self.debug,
|
||||||
int_enabled: self.int_enabled,
|
int_enabled: self.int_enabled,
|
||||||
int_level: self.int_level,
|
int_level: self.int_level,
|
||||||
read_fifo: self.read_fifo.clone().into(),
|
read_fifo: self.read_fifo.clone().into(),
|
||||||
@@ -167,6 +176,7 @@ impl Pl011 {
|
|||||||
self.rsr = state.rsr;
|
self.rsr = state.rsr;
|
||||||
self.cr = state.cr;
|
self.cr = state.cr;
|
||||||
self.dmacr = state.dmacr;
|
self.dmacr = state.dmacr;
|
||||||
|
self.debug = state.debug;
|
||||||
self.int_enabled = state.int_enabled;
|
self.int_enabled = state.int_enabled;
|
||||||
self.int_level = state.int_level;
|
self.int_level = state.int_level;
|
||||||
self.read_fifo = state.read_fifo.clone().into();
|
self.read_fifo = state.read_fifo.clone().into();
|
||||||
@@ -280,13 +290,50 @@ impl Pl011 {
|
|||||||
return Err(Error::DmaNotImplemented);
|
return Err(Error::DmaNotImplemented);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UARTDEBUG => {
|
||||||
|
self.debug = val;
|
||||||
|
self.handle_debug();
|
||||||
|
}
|
||||||
off => {
|
off => {
|
||||||
|
debug!("PL011: Bad write offset, offset: {}", off);
|
||||||
return Err(Error::BadWriteOffset(off));
|
return Err(Error::BadWriteOffset(off));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_debug(&self) {
|
||||||
|
let elapsed = self.timestamp.elapsed();
|
||||||
|
|
||||||
|
match self.debug {
|
||||||
|
0x00..=0x1f => info!(
|
||||||
|
"[Debug I/O port: Firmware code: 0x{:x}] {}.{:>06} seconds",
|
||||||
|
self.debug,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
),
|
||||||
|
0x20..=0x3f => info!(
|
||||||
|
"[Debug I/O port: Bootloader code: 0x{:x}] {}.{:>06} seconds",
|
||||||
|
self.debug,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
),
|
||||||
|
0x40..=0x5f => info!(
|
||||||
|
"[Debug I/O port: Kernel code: 0x{:x}] {}.{:>06} seconds",
|
||||||
|
self.debug,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
),
|
||||||
|
0x60..=0x7f => info!(
|
||||||
|
"[Debug I/O port: Userspace code: 0x{:x}] {}.{:>06} seconds",
|
||||||
|
self.debug,
|
||||||
|
elapsed.as_secs(),
|
||||||
|
elapsed.as_micros()
|
||||||
|
),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
|
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
|
||||||
self.irq.trigger(0)
|
self.irq.trigger(0)
|
||||||
}
|
}
|
||||||
@@ -327,6 +374,7 @@ impl BusDevice for Pl011 {
|
|||||||
UARTRIS => self.int_level,
|
UARTRIS => self.int_level,
|
||||||
UARTMIS => (self.int_level & self.int_enabled),
|
UARTMIS => (self.int_level & self.int_enabled),
|
||||||
UARTDMACR => self.dmacr,
|
UARTDMACR => self.dmacr,
|
||||||
|
UARTDEBUG => self.debug,
|
||||||
_ => {
|
_ => {
|
||||||
read_ok = false;
|
read_ok = false;
|
||||||
0
|
0
|
||||||
@@ -404,6 +452,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -448,6 +497,7 @@ mod tests {
|
|||||||
String::from(SERIAL_NAME),
|
String::from(SERIAL_NAME),
|
||||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||||
Some(Box::new(pl011_out.clone())),
|
Some(Box::new(pl011_out.clone())),
|
||||||
|
Instant::now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
|
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
|
||||||
@@ -468,6 +518,7 @@ mod tests {
|
|||||||
String::from(SERIAL_NAME),
|
String::from(SERIAL_NAME),
|
||||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||||
Some(Box::new(pl011_out)),
|
Some(Box::new(pl011_out)),
|
||||||
|
Instant::now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ extern crate bitflags;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub mod gic;
|
pub mod gic;
|
||||||
@@ -21,7 +20,6 @@ pub mod interrupt_controller;
|
|||||||
pub mod ioapic;
|
pub mod ioapic;
|
||||||
pub mod legacy;
|
pub mod legacy;
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
|
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ Reboot the VM | `/vm.reboot` | N/A
|
|||||||
Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted
|
Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted
|
||||||
Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted
|
Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted
|
||||||
Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused
|
Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused
|
||||||
|
Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig`| N/A | The VM is paused
|
||||||
|
Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted
|
||||||
Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted
|
Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted
|
||||||
Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted
|
Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted
|
||||||
Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted
|
Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted
|
||||||
@@ -98,6 +100,7 @@ Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig`
|
|||||||
Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
||||||
Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
||||||
Add userspace PCI device to the VM | `/vm.add-user-device`| `/schemas/VmAddUserDevice`| `/schemas/PciDeviceInfo` | The VM is booted
|
Add userspace PCI device to the VM | `/vm.add-user-device`| `/schemas/VmAddUserDevice`| `/schemas/PciDeviceInfo` | The VM is booted
|
||||||
|
Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
||||||
Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted
|
||||||
Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted
|
Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted
|
||||||
Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted
|
Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted
|
||||||
|
|||||||
76
docs/balloon.md
Normal file
76
docs/balloon.md
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Balloon
|
||||||
|
|
||||||
|
Cloud Hypervisor implements a balloon device based on the VIRTIO specification.
|
||||||
|
Its main purpose is to provide the host a way to reclaim memory by controlling
|
||||||
|
the amount of memory visible to the guest. But it also provides some interesting
|
||||||
|
features related to guest memory management.
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
`BalloonConfig` (known as `--balloon` from the CLI perspective) contains the
|
||||||
|
list of parameters available for the balloon device.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct BalloonConfig {
|
||||||
|
pub size: u64,
|
||||||
|
pub deflate_on_oom: bool,
|
||||||
|
pub free_page_reporting: bool,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
--balloon <balloon> Balloon parameters "size=<balloon_size>,deflate_on_oom=on|off,free_page_reporting=on|off"
|
||||||
|
```
|
||||||
|
|
||||||
|
### `size`
|
||||||
|
|
||||||
|
Size of the balloon device. It is subtracted from the VM's total size. For
|
||||||
|
instance, if creating a VM with 4GiB of RAM, along with a balloon of 1GiB, the
|
||||||
|
guest will be able to use 3GiB of accessible memory. The guest sees all the RAM
|
||||||
|
and unless it is balloon enlightened is entitled to all of it.
|
||||||
|
|
||||||
|
This parameter is mandatory.
|
||||||
|
|
||||||
|
Value is an unsigned integer of 64 bits corresponding to the balloon size in
|
||||||
|
bytes.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--balloon size=1G
|
||||||
|
```
|
||||||
|
|
||||||
|
### `deflate_on_oom`
|
||||||
|
|
||||||
|
Allow the guest to deflate the balloon if running Out Of Memory (OOM). Assuming
|
||||||
|
the balloon size is greater than 0, this means the guest is allowed to reduce
|
||||||
|
the balloon size all the way down to 0 if this can help recover from the OOM
|
||||||
|
event.
|
||||||
|
|
||||||
|
This parameter is optional.
|
||||||
|
|
||||||
|
Value is a boolean set to `off` by default.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--ballloon size=2G,deflate_on_oom=on
|
||||||
|
```
|
||||||
|
|
||||||
|
### `free_page_reporting`
|
||||||
|
|
||||||
|
Allow the guest to report lists of free pages. This feature doesn't require the
|
||||||
|
balloon to be of any specific size as it doesn't impact the balloon size. The
|
||||||
|
guest can let the VMM know about pages that are free after they have been used.
|
||||||
|
Based on this information, the VMM can advise the host that it doesn't need
|
||||||
|
these pages anymore.
|
||||||
|
|
||||||
|
This parameter is optional.
|
||||||
|
|
||||||
|
Value is a boolean set to `off` by default.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--ballloon size=0,free_page_reporting=on
|
||||||
|
```
|
||||||
24
docs/cpu.md
24
docs/cpu.md
@@ -17,11 +17,12 @@ struct CpusConfig {
|
|||||||
kvm_hyperv: bool,
|
kvm_hyperv: bool,
|
||||||
max_phys_bits: u8,
|
max_phys_bits: u8,
|
||||||
affinity: Option<Vec<CpuAffinity>>,
|
affinity: Option<Vec<CpuAffinity>>,
|
||||||
|
features: CpuFeatures,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>
|
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
|
||||||
```
|
```
|
||||||
|
|
||||||
### `boot`
|
### `boot`
|
||||||
@@ -187,3 +188,24 @@ _Example_
|
|||||||
In this example, assuming the host has 4 CPUs, vCPU 0 will run exclusively on
|
In this example, assuming the host has 4 CPUs, vCPU 0 will run exclusively on
|
||||||
host CPUs 2 and 3, while vCPU 1 will run exclusively on host CPUs 0 and 1.
|
host CPUs 2 and 3, while vCPU 1 will run exclusively on host CPUs 0 and 1.
|
||||||
Because nothing is defined for vCPU 2, it can run on any of the 4 host CPUs.
|
Because nothing is defined for vCPU 2, it can run on any of the 4 host CPUs.
|
||||||
|
|
||||||
|
### `features`
|
||||||
|
|
||||||
|
Set of CPU features to enable.
|
||||||
|
|
||||||
|
This option allows the user to enable a set of CPU features that are disabled
|
||||||
|
by default otherwise.
|
||||||
|
|
||||||
|
The currently available feature set is: `amx`.
|
||||||
|
|
||||||
|
The `amx` feature will enable the x86 extension adding hardware units for
|
||||||
|
matrix operations (int and float dot products). The goal of the extension is to
|
||||||
|
provide performance enhancements for these common operations.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus features=amx
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example the amx CPU feature will be enabled for the VMM.
|
||||||
|
|||||||
66
docs/fs.md
66
docs/fs.md
@@ -1,14 +1,18 @@
|
|||||||
# How to use virtio-fs
|
# How to use virtio-fs
|
||||||
|
|
||||||
In the context of virtualization, it is always convenient to be able to share a directory from the host with the guest.
|
In the context of virtualization, it is always convenient to be able to share a
|
||||||
|
directory from the host with the guest.
|
||||||
|
|
||||||
__virtio-fs__, also known as __vhost-user-fs__ is a virtual device defined by the VIRTIO specification which allows any VMM to perform filesystem sharing.
|
__virtio-fs__, also known as __vhost-user-fs__ is a virtual device defined by
|
||||||
|
the VIRTIO specification which allows any VMM to perform filesystem sharing.
|
||||||
|
|
||||||
## Pre-requisites
|
## Pre-requisites
|
||||||
|
|
||||||
### The daemon
|
### The daemon
|
||||||
|
|
||||||
This virtual device relies on the _vhost-user_ protocol, which assumes the backend (device emulation) is handled by a dedicated process running on the host. This daemon is called __virtiofsd__ and needs to be present on the host.
|
This virtual device relies on the _vhost-user_ protocol, which assumes the
|
||||||
|
backend (device emulation) is handled by a dedicated process running on the
|
||||||
|
host. This daemon is called __virtiofsd__ and needs to be present on the host.
|
||||||
|
|
||||||
_Build virtiofsd_
|
_Build virtiofsd_
|
||||||
```bash
|
```bash
|
||||||
@@ -31,25 +35,35 @@ _Run virtiofsd_
|
|||||||
--cache=never
|
--cache=never
|
||||||
```
|
```
|
||||||
|
|
||||||
The `cache=never` option should be the default when using `virtiofsd` with the __cloud-hypervisor__ VMM. This prevents from using the guest page cache, which reduces the memory footprint of the guest. When running multiple virtual machines on the same host, this will let the host deal with page cache, which will increase the density of virtual machines which can be launched.
|
The `cache=never` option is the default when using `virtiofsd` with
|
||||||
|
Cloud Hypervisor. This prevents from using the host page cache, reducing the
|
||||||
|
overall footprint on host memory. This increases the maximum density of virtual
|
||||||
|
machines that can be launched on a single host.
|
||||||
|
|
||||||
The `cache=always` option will allow for the guest page cache to be used, which will increase the memory footprint of the guest. This option should be used only for specific use cases where a single VM is going to be running on a host.
|
The `cache=always` option will allow the host page cache to be used, which can
|
||||||
|
result in better performance for the guest's workload at the cost of increasing
|
||||||
|
the footprint on host memory.
|
||||||
|
|
||||||
### Kernel support
|
### Kernel support
|
||||||
|
|
||||||
Modern Linux kernels starting (at least v5.10) have support for virtio-fs. Use
|
Modern Linux kernels (at least v5.10) have support for virtio-fs. Use of older
|
||||||
of older kernels, with additional patches, are not supported.
|
kernels, with additional patches, are not supported.
|
||||||
|
|
||||||
## How to share directories with cloud-hypervisor
|
## How to share directories with cloud-hypervisor
|
||||||
|
|
||||||
### Start the VM
|
### Start the VM
|
||||||
Once the daemon is running, the option `--fs` from __cloud-hypervisor__ needs to be used.
|
|
||||||
|
|
||||||
Direct kernel boot is the preferred option, but we can boot from an EFI cloud image if it contains a recent enough kernel.
|
Once the daemon is running, the option `--fs` from Cloud Hypervisor needs
|
||||||
|
to be used.
|
||||||
|
|
||||||
Because _vhost-user_ expects a dedicated process (__virtiofsd__ in this case) to be able to access the guest RAM to communicate through the _virtqueues_ with the driver running in the guest, `--memory` option needs to be slightly modified. It must specify `shared=on` to share the memory pages so that an external process can access them.
|
Both direct kernel boot and EFI firmware can be used to boot a VM with
|
||||||
|
virtio-fs, given that the cloud image contains a recent enough kernel.
|
||||||
|
|
||||||
Assuming you have `focal-server-cloudimg-amd64.raw` and `vmlinux` on your system, here is the __cloud-hypervisor__ command you need to run:
|
Correct functioning of `--fs` requires `--memory shared=on` to facilitate
|
||||||
|
interprocess memory sharing.
|
||||||
|
|
||||||
|
Assuming you have `focal-server-cloudimg-amd64.raw` and `vmlinux` on your
|
||||||
|
system, here is the Cloud Hypervisor command you need to run:
|
||||||
```bash
|
```bash
|
||||||
./cloud-hypervisor \
|
./cloud-hypervisor \
|
||||||
--cpus boot=1 \
|
--cpus boot=1 \
|
||||||
@@ -60,26 +74,20 @@ Assuming you have `focal-server-cloudimg-amd64.raw` and `vmlinux` on your system
|
|||||||
--fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512
|
--fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, DAX is enabled with a cache window of 8GiB. You can specify a custom size (let's say 4GiB for this example) for the cache by explicitly setting DAX and the cache size:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
--fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512,dax=on,cache_size=4G
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
In case you don't want to use a shared window of cache to pass the shared files content, this means you will have to explicitly disable DAX with `dax=off`. Note that in this case, the `cache_size` parameter will be ignored.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
--fs tag=myfs,socket=/tmp/virtiofs,num_queues=1,queue_size=512,dax=off
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mount the shared directory
|
### Mount the shared directory
|
||||||
The last step is to mount the shared directory inside the guest, using the `virtiofs` filesystem type.
|
|
||||||
|
The last step is to mount the shared directory inside the guest, using the
|
||||||
|
`virtiofs` filesystem type.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir mount_dir
|
mkdir mount_dir
|
||||||
mount -t virtiofs -o dax myfs mount_dir/
|
mount -t virtiofs myfs mount_dir/
|
||||||
```
|
```
|
||||||
The `tag` needs to be consistent with what has been provided through the __cloud-hypervisor__ command line, which happens to be `myfs` in this example.
|
|
||||||
|
|
||||||
The `-o dax` option must be removed in case the shared cache region is not enabled from the VMM.
|
The `tag` needs to be consistent with what has been provided through the
|
||||||
|
Cloud Hypervisor command line, which happens to be `myfs` in this example.
|
||||||
|
|
||||||
|
## DAX feature
|
||||||
|
|
||||||
|
Given the DAX feature is not stable yet from a daemon standpoint, it is not
|
||||||
|
available in Cloud Hypervisor.
|
||||||
@@ -55,9 +55,9 @@ cargo build --features tdx
|
|||||||
```
|
```
|
||||||
|
|
||||||
And run a TDX VM by providing the firmware previously built, along with the
|
And run a TDX VM by providing the firmware previously built, along with the
|
||||||
guest image containing the TDX enlightened kernel. Assuming the guest kernel
|
guest image containing the TDX enlightened kernel. The latest image
|
||||||
command line contains `console=hvc0` (printing to the `virtio-console` device),
|
`td-guest-rhel8.5.raw` contains `console=hvc0` on the kernel boot parameters,
|
||||||
run Cloud Hypervisor as follows:
|
meaning it will be printing guest kernel logs to the `virtio-console` device.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./cloud-hypervisor \
|
./cloud-hypervisor \
|
||||||
@@ -67,8 +67,8 @@ run Cloud Hypervisor as follows:
|
|||||||
--disk path=tdx_guest_img
|
--disk path=tdx_guest_img
|
||||||
```
|
```
|
||||||
|
|
||||||
And here is the alternative command when looking for debug logs (assuming the
|
And here is the alternative command when looking for debug logs from the
|
||||||
guest kernel command line contains `console=ttyS0`):
|
firmware:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./cloud-hypervisor \
|
./cloud-hypervisor \
|
||||||
@@ -76,8 +76,8 @@ guest kernel command line contains `console=ttyS0`):
|
|||||||
--cpus boot=1 \
|
--cpus boot=1 \
|
||||||
--memory size=1G \
|
--memory size=1G \
|
||||||
--disk path=tdx_guest_img \
|
--disk path=tdx_guest_img \
|
||||||
--serial tty \
|
--serial file=/tmp/ch_serial \
|
||||||
--console off
|
--console tty
|
||||||
```
|
```
|
||||||
|
|
||||||
### TDShim
|
### TDShim
|
||||||
@@ -97,8 +97,14 @@ option as well.
|
|||||||
./cloud-hypervisor \
|
./cloud-hypervisor \
|
||||||
--tdx firmware=tdshim \
|
--tdx firmware=tdshim \
|
||||||
--kernel bzImage \
|
--kernel bzImage \
|
||||||
--cmdline "root=/dev/vda1 console=hvc0 rw tdx_allow_acpi=MCFG"
|
--cmdline "root=/dev/vda3 console=hvc0 rw"
|
||||||
--cpus boot=1 \
|
--cpus boot=1 \
|
||||||
--memory size=1G \
|
--memory size=1G \
|
||||||
--disk path=tdx_guest_img
|
--disk path=tdx_guest_img
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Guest kernel disables serial ports
|
||||||
|
|
||||||
|
The latest guest kernel that can be found in the latest image
|
||||||
|
`td-guest-rhel8.5.raw` disabled the support for serial ports. This means adding
|
||||||
|
`console=ttyS0` will have no effect and will not print any log from the guest.
|
||||||
@@ -24,8 +24,8 @@ bucket is unbounded in speed which allows for bursts bound in size by
|
|||||||
the amount of tokens available. Once the token bucket is empty,
|
the amount of tokens available. Once the token bucket is empty,
|
||||||
consumption speed is bound by the "refill-rate". Similarly, Cloud
|
consumption speed is bound by the "refill-rate". Similarly, Cloud
|
||||||
Hypervisor provides another three options for limiting I/O operations,
|
Hypervisor provides another three options for limiting I/O operations,
|
||||||
i.e., `ops_size` (I/O operations), `bw_one_time_burst` (I/O operations),
|
i.e., `ops_size` (I/O operations), `ops_one_time_burst` (I/O operations),
|
||||||
and `bw_refill_time` (ms).
|
and `ops_refill_time` (ms).
|
||||||
|
|
||||||
One caveat in the I/O throttling is that every-time the bucket gets
|
One caveat in the I/O throttling is that every-time the bucket gets
|
||||||
empty, it will stop I/O operations for a fixed amount of time
|
empty, it will stop I/O operations for a fixed amount of time
|
||||||
|
|||||||
@@ -231,3 +231,38 @@ Last thing is to start the L2 guest with the huge pages memory backend.
|
|||||||
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
||||||
--device path=/sys/bus/pci/devices/0000:00:04.0
|
--device path=/sys/bus/pci/devices/0000:00:04.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Dedicated IOMMU PCI segments
|
||||||
|
|
||||||
|
To facilitate hotplug of devices that require being behind an IOMMU it is
|
||||||
|
possible to mark entire PCI segments as behind the IOMMU.
|
||||||
|
|
||||||
|
This is accomplished through `--platform
|
||||||
|
num_pci_segments=<number_of_segments>,iommu_segments=<range of segments>` or
|
||||||
|
via the equivalents in `PlatformConfig` for the API.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./cloud-hypervisor \
|
||||||
|
--api-socket=/tmp/api \
|
||||||
|
--cpus boot=1 \
|
||||||
|
--memory size=4G,hugepages=on \
|
||||||
|
--disk path=focal-server-cloudimg-amd64.raw \
|
||||||
|
--kernel custom-vmlinux \
|
||||||
|
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
||||||
|
--platform num_pci_segments=2,iommu_segments=1
|
||||||
|
```
|
||||||
|
|
||||||
|
This adds a second PCI segment to the platform behind the IOMMU. A VFIO device
|
||||||
|
requiring the IOMMU then may be hotplugged:
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./ch-remote --api-socket=/tmp/api add-device path=/sys/bus/pci/devices/0000:00:04.0,iommu=on,pci_segment=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Devices that cannot be placed behind an IOMMU (e.g. lacking an `iommu=` option)
|
||||||
|
cannot be placed on the IOMMU segments.
|
||||||
|
|
||||||
|
|||||||
29
docs/performance_metrics.md
Normal file
29
docs/performance_metrics.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Performance Metrics
|
||||||
|
|
||||||
|
Cloud Hypervisor provides a [performance metrics](https://github.com/cloud-hypervisor/cloud-hypervisor/tree/main/performance-metrics)
|
||||||
|
binary for users to generate metrics data from their own
|
||||||
|
environment. This document describes how to generate metrics data
|
||||||
|
quickly by using Cloud Hypervisor's development script,
|
||||||
|
e.g. `dev_cli.sh`. The only prerequisite is [Docker installation](https://docs.docker.com/engine/install/).
|
||||||
|
Please note that upon its first invocation, this script will pull a
|
||||||
|
fairly large container image.
|
||||||
|
|
||||||
|
To generate metrics data for all available performance tests (including
|
||||||
|
boot time, block I/O throughput, and network throughput & latency) and
|
||||||
|
output the result into a json file:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./scripts/dev_cli.sh tests --metrics -- -- --report-file /tmp/metrics.json
|
||||||
|
```
|
||||||
|
|
||||||
|
To get a list of available performance tests:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./scripts/dev_cli.sh tests --metrics -- -- --list-tests
|
||||||
|
```
|
||||||
|
|
||||||
|
To generate metrics data for selected performance tests, e.g. boot time only:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./scripts/dev_cli.sh tests --metrics -- -- --report-file /tmp/metrics.json --test-filter boot_time
|
||||||
|
```
|
||||||
103
docs/releases.md
Executable file
103
docs/releases.md
Executable file
@@ -0,0 +1,103 @@
|
|||||||
|
# Release Documentation
|
||||||
|
|
||||||
|
## Abstract
|
||||||
|
|
||||||
|
This document provides guidance to users, downstream maintainers and
|
||||||
|
any other consumers of the Cloud Hypervisor project, this document
|
||||||
|
describes the release process, release cadence, stability expectations and
|
||||||
|
related topics.
|
||||||
|
|
||||||
|
## Basic Terms
|
||||||
|
|
||||||
|
### Stability
|
||||||
|
|
||||||
|
For Cloud Hypervisor the following areas are subject to stability guarantees:
|
||||||
|
|
||||||
|
- [REST API](api.md#rest-api)
|
||||||
|
- [Command line options](api.md#command-line-interface)
|
||||||
|
- [Device Model](device_model.md)
|
||||||
|
- Device tree, device list, ACPI, Hyper-V enlightenments and any other
|
||||||
|
features exposed to guest
|
||||||
|
- KVM compatibility
|
||||||
|
- Rust edition compatibility
|
||||||
|
|
||||||
|
This list is incomplete but this document serves as a best effort guide to stability
|
||||||
|
across releases.
|
||||||
|
|
||||||
|
### Experimental features
|
||||||
|
|
||||||
|
Experimental features are under active development and no guarantees are made about their stability.
|
||||||
|
|
||||||
|
List of experimental features:
|
||||||
|
|
||||||
|
- TDX
|
||||||
|
- vfio-user
|
||||||
|
- vDPA
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
Security fixes should be included in a new point release.
|
||||||
|
|
||||||
|
For security issues an advisory will be published via the GitHub security advisory process along with the release. Watching the project on GitHub will notify you of those issues.
|
||||||
|
|
||||||
|
## Releases
|
||||||
|
|
||||||
|
### Versioning
|
||||||
|
|
||||||
|
The versioning scheme uses `MAJOR.POINT` pattern:
|
||||||
|
|
||||||
|
- `MAJOR` can introduce incompatible changes along with support for new features. Changes to the [API](api.md#rest-api),
|
||||||
|
[CLI options](api.md#command-line-interface) and [device model](device_model.md)
|
||||||
|
require a notice at least 2 releases in advance for the actual change to take
|
||||||
|
place.
|
||||||
|
- `POINT` contains bug fixes and/or security fixes.
|
||||||
|
|
||||||
|
### Major Release Cadence
|
||||||
|
|
||||||
|
Cloud Hypervisor is under active development. A new major release is issued approximately
|
||||||
|
every 6 weeks. Point releases are issued on demand, when important bug fixes are in
|
||||||
|
the queue. A major release would receive bug fixes for the next two cycles (~12 weeks)
|
||||||
|
and then be considered EOL.
|
||||||
|
|
||||||
|
```
|
||||||
|
+ - Active release support
|
||||||
|
E - EOL
|
||||||
|
|
||||||
|
2021 2022 2023
|
||||||
|
| | | | | | | | |
|
||||||
|
18.0 | | | ++++++++E
|
||||||
|
19.0 | | | |++++++++E
|
||||||
|
20.0 | | | | ++++++++E
|
||||||
|
21.0 | | | | | ++++++++E
|
||||||
|
22.0 | | | | | +++++++++E
|
||||||
|
23.0 | | | | | | +++++++++E
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Major Release Stability Considerations
|
||||||
|
|
||||||
|
Snapshot/restore support is not compatible across `MAJOR` versions.
|
||||||
|
Live migration support is not compatible across `MAJOR` versions.
|
||||||
|
|
||||||
|
### LTS Release Cadence
|
||||||
|
|
||||||
|
A regular release is promoted to LTS every 12 months. An LTS release is supported for 18 months. This gives a 6 months window for users to move to the new LTS.
|
||||||
|
|
||||||
|
```
|
||||||
|
+ - Active release support
|
||||||
|
E - EOL
|
||||||
|
|
||||||
|
2022 2023 2024 2025 2026
|
||||||
|
| | | | | | | | | | | | | | | | |
|
||||||
|
23.0 | |+++++++++++++++++++++++++++++E
|
||||||
|
43.0 | | | | | |+++++++++++++++++++++++++++++E
|
||||||
|
63.0 | | | | | | | | | |+++++++++++++++++++++++++++++E
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### LTS Stablity Considerations
|
||||||
|
|
||||||
|
An LTS release is just a `MAJOR` release for which point releases are made for
|
||||||
|
longer following the same rules for what can be backported to a `POINT` release.
|
||||||
|
The focus lays on critical and security bug fixes which are pulled at the
|
||||||
|
maintainer's discretion.
|
||||||
154
docs/vdpa.md
Normal file
154
docs/vdpa.md
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# Virtio Data Path Acceleration
|
||||||
|
|
||||||
|
vDPA aims at achieving bare-metal performance for devices passed into a virtual
|
||||||
|
machine. It is an alternative to VFIO, as it provides a simpler solution for
|
||||||
|
achieving migration.
|
||||||
|
|
||||||
|
It is a kernel framework introduced recently to handle devices complying with
|
||||||
|
the VIRTIO specification on their data-path, while the control path is vendor
|
||||||
|
specific. In practice, virtqueues are accessed directly through DMA mechanism
|
||||||
|
between the hardware and the guest. The control path is accessed through the
|
||||||
|
vDPA framework, being exposed through the vhost interface as a vhost-vdpa
|
||||||
|
device.
|
||||||
|
|
||||||
|
Because DMA accesses between device and guest are going through virtqueues,
|
||||||
|
migration can be achieved without requiring device's driver to implement any
|
||||||
|
specific migration support. In case of VFIO, each vendor is expected to provide
|
||||||
|
an implementation of the VFIO migration framework, complicating things as it
|
||||||
|
must be done for each and every device's driver.
|
||||||
|
|
||||||
|
The official [website](https://vdpa-dev.gitlab.io/) contains some extensive
|
||||||
|
documentation on the topic.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
`VdpaConfig` (known as `--vdpa` from the CLI perspective) contains the list of
|
||||||
|
parameters available for the vDPA device.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct VdpaConfig {
|
||||||
|
path: PathBuf,
|
||||||
|
num_queues: usize,
|
||||||
|
id: Option<String>,
|
||||||
|
pci_segment: u16,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
--vdpa <vdpa> vDPA device "path=<device_path>,num_queues=<number_of_queues>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### `path`
|
||||||
|
|
||||||
|
Path of the vDPA device. Usually `/dev/vhost-vdpa-X`.
|
||||||
|
|
||||||
|
This parameter is mandatory.
|
||||||
|
|
||||||
|
Value is a string.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--vdpa path=/dev/vhost-vdpa-0
|
||||||
|
```
|
||||||
|
|
||||||
|
### `num_queues`
|
||||||
|
|
||||||
|
Number of virtqueues supported by the vDPA device.
|
||||||
|
|
||||||
|
This parameter is optional.
|
||||||
|
|
||||||
|
Value is an unsigned integer set to `1` by default.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--vdpa path=/dev/vhost-vdpa-0,num_queues=2
|
||||||
|
```
|
||||||
|
|
||||||
|
### `id`
|
||||||
|
|
||||||
|
Identifier of the vDPA device.
|
||||||
|
|
||||||
|
This parameter is optional. If provided, it must be unique across the entire
|
||||||
|
virtual machine.
|
||||||
|
|
||||||
|
Value is a string.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--vdpa path=/dev/vhost-vdpa-0,id=vdpa0
|
||||||
|
```
|
||||||
|
|
||||||
|
### `pci_segment`
|
||||||
|
|
||||||
|
PCI segment number to which the vDPA device should be attached to.
|
||||||
|
|
||||||
|
This parameter is optional.
|
||||||
|
|
||||||
|
Value is an unsigned integer of 16 bits set to `0` by default.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--vdpa path=/dev/vhost-vdpa-0,pci_segment=1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example with vDPA block simulator
|
||||||
|
|
||||||
|
The vDPA framework provides a simulator with both `virtio-block` and
|
||||||
|
`virtio-net` implementations. This is very useful for testing vDPA when we
|
||||||
|
don't have access to the specific hardware.
|
||||||
|
|
||||||
|
Given the host kernel has the appropriate modules available, let's load them
|
||||||
|
all:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo modprobe vdpa
|
||||||
|
sudo modprobe vhost_vdpa
|
||||||
|
sudo modprobe vdpa_sim
|
||||||
|
sudo modprobe vdpa_sim_blk
|
||||||
|
```
|
||||||
|
|
||||||
|
Given you have the `iproute2/vdpa` tool installed, let's now create the
|
||||||
|
`virtio-block` vDPA device:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo vdpa dev add name vdpa-blk1 mgmtdev vdpasim_blk
|
||||||
|
sudo chown $USER:$USER /dev/vhost-vdpa-0
|
||||||
|
sudo chmod 660 /dev/vhost-vdpa-0
|
||||||
|
```
|
||||||
|
|
||||||
|
Increase the maximum locked memory to ensure setting up IOMMU mappings will
|
||||||
|
succeed:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ulimit -l unlimited
|
||||||
|
```
|
||||||
|
|
||||||
|
Start Cloud Hypervisor:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cloud-hypervisor \
|
||||||
|
--cpus boot=1 \
|
||||||
|
--memory size=1G,hugepages=on \
|
||||||
|
--disk path=focal-server-cloudimg-amd64.raw \
|
||||||
|
--kernel vmlinux \
|
||||||
|
--cmdline "root=/dev/vda1 console=hvc0" \
|
||||||
|
--vdpa path=/dev/vhost-vdpa-0,num_queues=1
|
||||||
|
```
|
||||||
|
|
||||||
|
The `virtio-block` device backed by the vDPA simulator can be found as
|
||||||
|
`/dev/vdb` in the guest:
|
||||||
|
|
||||||
|
```
|
||||||
|
cloud@cloud:~$ lsblk
|
||||||
|
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
||||||
|
nullb0 252:0 0 250G 0 disk
|
||||||
|
vda 254:0 0 2.2G 0 disk
|
||||||
|
├─vda1 254:1 0 2.1G 0 part /
|
||||||
|
├─vda14 254:14 0 4M 0 part
|
||||||
|
└─vda15 254:15 0 106M 0 part /boot/efi
|
||||||
|
vdb 254:16 0 128M 0 disk
|
||||||
|
```
|
||||||
@@ -75,8 +75,7 @@ Here is an example how to create a bridge and add two DPDK ports to it
|
|||||||
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
|
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
|
||||||
# create two DPDK ports and add them to the bridge
|
# create two DPDK ports and add them to the bridge
|
||||||
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
|
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
|
||||||
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2
|
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
|
||||||
type=dpdkvhostuser
|
|
||||||
# set the number of rx queues
|
# set the number of rx queues
|
||||||
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
|
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
|
||||||
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
|
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
name = "event_monitor"
|
name = "event_monitor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
serde = { version = "1.0.136", features = ["rc"] }
|
serde = { version = "1.0.137", features = ["rc", "derive"] }
|
||||||
serde_derive = "1.0.136"
|
serde_json = "1.0.81"
|
||||||
serde_json = "1.0.79"
|
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
#[macro_use]
|
use serde::Serialize;
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
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::Write;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
@@ -50,6 +49,9 @@ pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>
|
|||||||
properties,
|
properties,
|
||||||
};
|
};
|
||||||
serde_json::to_writer_pretty(file, &e).ok();
|
serde_json::to_writer_pretty(file, &e).ok();
|
||||||
|
|
||||||
|
let mut file = file;
|
||||||
|
file.write_all(b"\n\n").ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
162
fuzz/Cargo.lock
generated
162
fuzz/Cargo.lock
generated
@@ -11,9 +11,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.55"
|
version = "1.0.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
|
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -47,7 +47,6 @@ dependencies = [
|
|||||||
"linux-loader",
|
"linux-loader",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
@@ -128,24 +127,33 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.1.5"
|
version = "3.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ced1892c55c910c1219e98d6fc8d71f6bddba7905866ce740066d8bfea859312"
|
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"clap_lex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"os_str_bytes",
|
|
||||||
"strsim",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"terminal_size",
|
"terminal_size",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "21.0.0"
|
version = "23.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -185,9 +193,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.1"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee6b9c9389584bcba988bd0836086789b7f87ad91892d6a83d5291dbb24524b5"
|
checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -234,7 +242,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -270,9 +277,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
|
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -306,7 +313,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -325,9 +331,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@@ -345,9 +351,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-bindings"
|
name = "kvm-bindings"
|
||||||
@@ -377,15 +383,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.119"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36a9a84a6e8b55dfefb04235e55edb2b9a2a18488fcae777a6bdaa6f06f1deb3"
|
checksum = "336244aaeab6a12df46480dc585802aa743a72d66b11937844c61bbca84c991d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -403,9 +409,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -416,12 +422,6 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
|
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -460,18 +460,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.14"
|
version = "0.2.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.9.0"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
@@ -479,18 +479,15 @@ version = "0.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435"
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pci"
|
name = "pci"
|
||||||
@@ -502,7 +499,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
@@ -518,11 +514,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.36"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -538,9 +534,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.15"
|
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 = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -556,9 +552,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remain"
|
name = "remain"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7"
|
checksum = "0c35270ea384ac1762895831cc8acb96f171468e52cec82ed9186f9416209fa4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -576,9 +572,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.9"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "seccompiler"
|
name = "seccompiler"
|
||||||
@@ -591,21 +587,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.6"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
|
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -614,9 +613,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.79"
|
version = "1.0.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -625,9 +624,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.13"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
|
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -656,13 +655,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.86"
|
version = "1.0.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-xid",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -695,18 +694,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.30"
|
version = "1.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.30"
|
version = "1.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -714,16 +713,16 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-ident"
|
||||||
version = "0.2.2"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "0.8.2"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
@@ -812,9 +811,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b56bf8f178fc500fe14505fca8b00dec76fc38f2304f461c8d9d7547982311d"
|
checksum = "53567fd9ab820e4f3cc156f24146882fee3c365194c3e1dea74723265f27fc88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -847,8 +846,8 @@ dependencies = [
|
|||||||
"rate_limiter",
|
"rate_limiter",
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
@@ -864,8 +863,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-queue"
|
name = "virtio-queue"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/rust-vmm/vm-virtio?branch=main#bbb22d43558a76cc7cc9c262c4be870a9e682a86"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88f2d73c184c18f8acc32dab77fcb6e3af92d53262538d3a68aa474810d6863c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -886,8 +886,8 @@ name = "vm-device"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"hypervisor",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"vfio-ioctls",
|
"vfio-ioctls",
|
||||||
@@ -902,9 +902,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#720e48e435b791ec6cb
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "339d4349c126fdcd87e034631d7274370cf19eb0e87b33166bcd956589fc72c5"
|
checksum = "767ed8aaebbff902e02e6d3749dc2baef55e46565f8a6414a065e5baee4b4a81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -917,7 +917,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
@@ -963,7 +962,6 @@ dependencies = [
|
|||||||
"qcow",
|
"qcow",
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|||||||
@@ -3,23 +3,23 @@ name = "cloud-hypervisor-fuzz"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["Automatically generated"]
|
authors = ["Automatically generated"]
|
||||||
publish = false
|
publish = false
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_util = { path = "../block_util" }
|
block_util = { path = "../block_util" }
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
libfuzzer-sys = "0.4.2"
|
libfuzzer-sys = "0.4.3"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
seccompiler = "0.2.0"
|
seccompiler = "0.2.0"
|
||||||
vhdx = { path = "../vhdx" }
|
vhdx = { path = "../vhdx" }
|
||||||
virtio-devices = { path = "../virtio-devices" }
|
virtio-devices = { path = "../virtio-devices" }
|
||||||
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio", branch = "main" }
|
virtio-queue = "0.3.0"
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vm-memory = "0.7.0"
|
vm-memory = "0.8.0"
|
||||||
|
|
||||||
[dependencies.cloud-hypervisor]
|
[dependencies.cloud-hypervisor]
|
||||||
path = ".."
|
path = ".."
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "hypervisor"
|
name = "hypervisor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Microsoft Authors"]
|
authors = ["Microsoft Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
license = "Apache-2.0 OR BSD-3-Clause"
|
license = "Apache-2.0 OR BSD-3-Clause"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -11,19 +11,18 @@ mshv = ["mshv-ioctls", "mshv-bindings"]
|
|||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.55"
|
anyhow = "1.0.57"
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.31"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
kvm-ioctls = { version = "0.11.0", optional = true }
|
kvm-ioctls = { version = "0.11.0", optional = true }
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.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.136", features = ["rc"] }
|
serde = { version = "1.0.137", features = ["rc", "derive"] }
|
||||||
serde_derive = "1.0.136"
|
serde_json = "1.0.81"
|
||||||
serde_json = "1.0.79"
|
vm-memory = { version = "0.8.0", features = ["backend-mmap", "backend-atomic"] }
|
||||||
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic"] }
|
|
||||||
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||||
|
|||||||
@@ -6,9 +6,8 @@
|
|||||||
|
|
||||||
use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
|
use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
|
||||||
use crate::arch::x86::emulator::instructions::*;
|
use crate::arch::x86::emulator::instructions::*;
|
||||||
use crate::arch::x86::regs::*;
|
use crate::arch::x86::regs::{CR0_PE, EFER_LMA};
|
||||||
use crate::arch::x86::*;
|
use crate::arch::x86::{segment_type_expand_down, segment_type_ro, Exception, SegmentRegisterOps};
|
||||||
use crate::arch::x86::{Exception, SegmentRegisterOps};
|
|
||||||
use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters};
|
use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use iced_x86::*;
|
use iced_x86::*;
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
use crate::aarch64::VcpuInit;
|
use crate::aarch64::VcpuInit;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::aarch64::{RegList, Register, StandardRegisters};
|
use crate::aarch64::{RegList, Register, StandardRegisters};
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
use crate::kvm::{TdxExitDetails, TdxExitStatus};
|
||||||
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
|
use crate::x86_64::SuspendRegisters;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::x86_64::Xsave;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::x86_64::{CpuId, LapicState};
|
use crate::x86_64::{CpuId, LapicState};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -23,12 +29,6 @@ use crate::CpuState;
|
|||||||
use crate::DeviceAttr;
|
use crate::DeviceAttr;
|
||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
use crate::MpState;
|
use crate::MpState;
|
||||||
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
|
||||||
use crate::SuspendRegisters;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use crate::Xsave;
|
|
||||||
#[cfg(feature = "tdx")]
|
|
||||||
use crate::{TdxExitDetails, TdxExitStatus};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
// Copyright 2018-2019 CrowdStrike, Inc.
|
// Copyright 2018-2019 CrowdStrike, Inc.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
use crate::kvm::TdxCapabilities;
|
||||||
use crate::vm::Vm;
|
use crate::vm::Vm;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::x86_64::CpuId;
|
use crate::x86_64::CpuId;
|
||||||
@@ -59,6 +61,11 @@ pub enum HypervisorError {
|
|||||||
///
|
///
|
||||||
#[error("Checking extensions:{0}")]
|
#[error("Checking extensions:{0}")]
|
||||||
CheckExtensions(#[source] anyhow::Error),
|
CheckExtensions(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
|
/// Failed to retrieve TDX capabilities
|
||||||
|
///
|
||||||
|
#[error("Failed to retrieve TDX capabilities:{0}")]
|
||||||
|
TdxCapabilities(#[source] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -105,4 +112,9 @@ pub trait Hypervisor: Send + Sync {
|
|||||||
/// Retrieve AArch64 host maximum IPA size supported by KVM.
|
/// Retrieve AArch64 host maximum IPA size supported by KVM.
|
||||||
///
|
///
|
||||||
fn get_host_ipa_limit(&self) -> i32;
|
fn get_host_ipa_limit(&self) -> i32;
|
||||||
|
///
|
||||||
|
/// Retrieve TDX capabilities
|
||||||
|
///
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
fn tdx_capabilities(&self) -> Result<TdxCapabilities>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use kvm_bindings::{
|
|||||||
pub use kvm_bindings::{
|
pub use kvm_bindings::{
|
||||||
kvm_one_reg as Register, kvm_regs as StandardRegisters, kvm_vcpu_init as VcpuInit, RegList,
|
kvm_one_reg as Register, kvm_regs as StandardRegisters, kvm_vcpu_init as VcpuInit, RegList,
|
||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
||||||
|
|
||||||
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ use crate::cpu;
|
|||||||
use crate::device;
|
use crate::device;
|
||||||
use crate::hypervisor;
|
use crate::hypervisor;
|
||||||
use crate::vec_with_array_field;
|
use crate::vec_with_array_field;
|
||||||
use crate::vm::{self, VmmOps};
|
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::{arm64_core_reg_id, offset__of};
|
use crate::{arm64_core_reg_id, offset__of};
|
||||||
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@@ -107,7 +107,6 @@ ioctl_iowr_nr!(KVM_MEMORY_ENCRYPT_OP, KVMIO, 0xba, std::os::raw::c_ulong);
|
|||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
enum TdxCommand {
|
enum TdxCommand {
|
||||||
#[allow(dead_code)]
|
|
||||||
Capabilities = 0,
|
Capabilities = 0,
|
||||||
InitVm,
|
InitVm,
|
||||||
InitVcpu,
|
InitVcpu,
|
||||||
@@ -127,6 +126,34 @@ pub enum TdxExitStatus {
|
|||||||
InvalidOperand,
|
InvalidOperand,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
const TDX_MAX_NR_CPUID_CONFIGS: usize = 6;
|
||||||
|
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct TdxCpuidConfig {
|
||||||
|
pub leaf: u32,
|
||||||
|
pub sub_leaf: u32,
|
||||||
|
pub eax: u32,
|
||||||
|
pub ebx: u32,
|
||||||
|
pub ecx: u32,
|
||||||
|
pub edx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct TdxCapabilities {
|
||||||
|
pub attrs_fixed0: u64,
|
||||||
|
pub attrs_fixed1: u64,
|
||||||
|
pub xfam_fixed0: u64,
|
||||||
|
pub xfam_fixed1: u64,
|
||||||
|
pub nr_cpuid_configs: u32,
|
||||||
|
pub padding: u32,
|
||||||
|
pub cpuid_configs: [TdxCpuidConfig; TDX_MAX_NR_CPUID_CONFIGS],
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
|
||||||
pub struct KvmVmState {}
|
pub struct KvmVmState {}
|
||||||
|
|
||||||
@@ -207,7 +234,7 @@ impl vm::Vm for KvmVm {
|
|||||||
fn create_vcpu(
|
fn create_vcpu(
|
||||||
&self,
|
&self,
|
||||||
id: u8,
|
id: u8,
|
||||||
vmmops: Option<Arc<dyn VmmOps>>,
|
vm_ops: Option<Arc<dyn VmOps>>,
|
||||||
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
||||||
let vc = self
|
let vc = self
|
||||||
.fd
|
.fd
|
||||||
@@ -217,7 +244,7 @@ impl vm::Vm for KvmVm {
|
|||||||
fd: vc,
|
fd: vc,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
msrs: self.msrs.clone(),
|
msrs: self.msrs.clone(),
|
||||||
vmmops,
|
vm_ops,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
hyperv_synic: AtomicBool::new(false),
|
hyperv_synic: AtomicBool::new(false),
|
||||||
};
|
};
|
||||||
@@ -257,6 +284,64 @@ impl vm::Vm for KvmVm {
|
|||||||
.unregister_ioevent(fd, addr, NoDatamatch)
|
.unregister_ioevent(fd, addr, NoDatamatch)
|
||||||
.map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into()))
|
.map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a routing entry
|
||||||
|
///
|
||||||
|
fn make_routing_entry(
|
||||||
|
&self,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> kvm_irq_routing_entry {
|
||||||
|
match &config {
|
||||||
|
InterruptSourceConfig::MsiIrq(cfg) => {
|
||||||
|
let mut kvm_route = kvm_irq_routing_entry {
|
||||||
|
gsi,
|
||||||
|
type_: KVM_IRQ_ROUTING_MSI,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
kvm_route.u.msi.address_lo = cfg.low_addr;
|
||||||
|
kvm_route.u.msi.address_hi = cfg.high_addr;
|
||||||
|
kvm_route.u.msi.data = cfg.data;
|
||||||
|
|
||||||
|
if self.check_extension(crate::kvm::Cap::MsiDevid) {
|
||||||
|
// On AArch64, there is limitation on the range of the 'devid',
|
||||||
|
// it can not be greater than 65536 (the max of u16).
|
||||||
|
//
|
||||||
|
// BDF can not be used directly, because 'segment' is in high
|
||||||
|
// 16 bits. The layout of the u32 BDF is:
|
||||||
|
// |---- 16 bits ----|-- 8 bits --|-- 5 bits --|-- 3 bits --|
|
||||||
|
// | segment | bus | device | function |
|
||||||
|
//
|
||||||
|
// Now that we support 1 bus only in a segment, we can build a
|
||||||
|
// 'devid' by replacing the 'bus' bits with the low 8 bits of
|
||||||
|
// 'segment' data.
|
||||||
|
// This way we can resolve the range checking problem and give
|
||||||
|
// different `devid` to all the devices. Limitation is that at
|
||||||
|
// most 256 segments can be supported.
|
||||||
|
//
|
||||||
|
let modified_devid = (cfg.devid & 0x00ff_0000) >> 8 | cfg.devid & 0xff;
|
||||||
|
|
||||||
|
kvm_route.flags = KVM_MSI_VALID_DEVID;
|
||||||
|
kvm_route.u.msi.__bindgen_anon_1.devid = modified_devid;
|
||||||
|
}
|
||||||
|
kvm_route
|
||||||
|
}
|
||||||
|
InterruptSourceConfig::LegacyIrq(cfg) => {
|
||||||
|
let mut kvm_route = kvm_irq_routing_entry {
|
||||||
|
gsi,
|
||||||
|
type_: KVM_IRQ_ROUTING_IRQCHIP,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
kvm_route.u.irqchip.irqchip = cfg.irqchip;
|
||||||
|
kvm_route.u.irqchip.pin = cfg.pin;
|
||||||
|
|
||||||
|
kvm_route
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets the GSI routing table entries, overwriting any previously set
|
/// Sets the GSI routing table entries, overwriting any previously set
|
||||||
/// entries, as per the `KVM_SET_GSI_ROUTING` ioctl.
|
/// entries, as per the `KVM_SET_GSI_ROUTING` ioctl.
|
||||||
@@ -525,7 +610,7 @@ impl vm::Vm for KvmVm {
|
|||||||
let data = TdxInitVm {
|
let data = TdxInitVm {
|
||||||
max_vcpus,
|
max_vcpus,
|
||||||
tsc_khz: 0,
|
tsc_khz: 0,
|
||||||
attributes: 1, // TDX1_TD_ATTRIBUTE_DEBUG,
|
attributes: 0,
|
||||||
cpuid: cpuid.as_fam_struct_ptr() as u64,
|
cpuid: cpuid.as_fam_struct_ptr() as u64,
|
||||||
mrconfigid: [0; 6],
|
mrconfigid: [0; 6],
|
||||||
mrowner: [0; 6],
|
mrowner: [0; 6],
|
||||||
@@ -762,13 +847,34 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
fn get_host_ipa_limit(&self) -> i32 {
|
fn get_host_ipa_limit(&self) -> i32 {
|
||||||
self.kvm.get_host_ipa_limit()
|
self.kvm.get_host_ipa_limit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Retrieve TDX capabilities
|
||||||
|
///
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
fn tdx_capabilities(&self) -> hypervisor::Result<TdxCapabilities> {
|
||||||
|
let data = TdxCapabilities {
|
||||||
|
nr_cpuid_configs: TDX_MAX_NR_CPUID_CONFIGS as u32,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
tdx_command(
|
||||||
|
&self.kvm.as_raw_fd(),
|
||||||
|
TdxCommand::Capabilities,
|
||||||
|
0,
|
||||||
|
&data as *const _ as u64,
|
||||||
|
)
|
||||||
|
.map_err(|e| hypervisor::HypervisorError::TdxCapabilities(e.into()))?;
|
||||||
|
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Vcpu struct for KVM
|
/// Vcpu struct for KVM
|
||||||
pub struct KvmVcpu {
|
pub struct KvmVcpu {
|
||||||
fd: VcpuFd,
|
fd: VcpuFd,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
msrs: MsrEntries,
|
msrs: MsrEntries,
|
||||||
vmmops: Option<Arc<dyn vm::VmmOps>>,
|
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
hyperv_synic: AtomicBool,
|
hyperv_synic: AtomicBool,
|
||||||
}
|
}
|
||||||
@@ -1008,8 +1114,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
Ok(run) => match run {
|
Ok(run) => match run {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
VcpuExit::IoIn(addr, data) => {
|
VcpuExit::IoIn(addr, data) => {
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
return vmmops
|
return vm_ops
|
||||||
.pio_read(addr.into(), data)
|
.pio_read(addr.into(), data)
|
||||||
.map(|_| cpu::VmExit::Ignore)
|
.map(|_| cpu::VmExit::Ignore)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||||
@@ -1019,8 +1125,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
VcpuExit::IoOut(addr, data) => {
|
VcpuExit::IoOut(addr, data) => {
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
return vmmops
|
return vm_ops
|
||||||
.pio_write(addr.into(), data)
|
.pio_write(addr.into(), data)
|
||||||
.map(|_| cpu::VmExit::Ignore)
|
.map(|_| cpu::VmExit::Ignore)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||||
@@ -1052,8 +1158,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VcpuExit::MmioRead(addr, data) => {
|
VcpuExit::MmioRead(addr, data) => {
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
return vmmops
|
return vm_ops
|
||||||
.mmio_read(addr, data)
|
.mmio_read(addr, data)
|
||||||
.map(|_| cpu::VmExit::Ignore)
|
.map(|_| cpu::VmExit::Ignore)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||||
@@ -1062,8 +1168,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
Ok(cpu::VmExit::MmioRead(addr, data))
|
Ok(cpu::VmExit::MmioRead(addr, data))
|
||||||
}
|
}
|
||||||
VcpuExit::MmioWrite(addr, data) => {
|
VcpuExit::MmioWrite(addr, data) => {
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
return vmmops
|
return vm_ops
|
||||||
.mmio_write(addr, data)
|
.mmio_write(addr, data)
|
||||||
.map(|_| cpu::VmExit::Ignore)
|
.map(|_| cpu::VmExit::Ignore)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
||||||
use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
|
use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ pub mod kvm;
|
|||||||
pub mod mshv;
|
pub mod mshv;
|
||||||
|
|
||||||
/// Hypevisor related module
|
/// Hypevisor related module
|
||||||
pub mod hypervisor;
|
mod hypervisor;
|
||||||
|
|
||||||
/// Vm related module
|
/// Vm related module
|
||||||
pub mod vm;
|
mod vm;
|
||||||
|
|
||||||
/// CPU related module
|
/// CPU related module
|
||||||
mod cpu;
|
mod cpu;
|
||||||
@@ -48,16 +48,32 @@ mod cpu;
|
|||||||
/// Device related module
|
/// Device related module
|
||||||
mod device;
|
mod device;
|
||||||
|
|
||||||
pub use crate::hypervisor::{Hypervisor, HypervisorError};
|
|
||||||
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
|
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
|
||||||
pub use device::{Device, HypervisorDeviceError};
|
pub use device::{Device, HypervisorDeviceError};
|
||||||
|
pub use hypervisor::{Hypervisor, HypervisorError};
|
||||||
|
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
|
||||||
|
pub use kvm::aarch64;
|
||||||
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
|
pub use kvm::x86_64;
|
||||||
|
// Aliased types exposed from both hypervisors
|
||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
pub use kvm::*;
|
pub use kvm::{
|
||||||
|
ClockData, CpuState, CreateDevice, DeviceAttr, DeviceFd, IoEventAddress, IrqRoutingEntry,
|
||||||
|
MemoryRegion, MpState, VcpuEvents, VcpuExit, VmState,
|
||||||
|
};
|
||||||
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
pub use mshv::*;
|
pub use mshv::x86_64;
|
||||||
pub use vm::{DataMatch, HypervisorVmError, Vm};
|
// Aliased types exposed from both hypervisors
|
||||||
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
|
pub use mshv::{
|
||||||
|
CpuState, CreateDevice, DeviceAttr, DeviceFd, IoEventAddress, IrqRoutingEntry, MemoryRegion,
|
||||||
|
MpState, VcpuEvents, VcpuExit, VmState,
|
||||||
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
pub use vm::{
|
||||||
|
DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig,
|
||||||
|
Vm, VmOps,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> {
|
pub fn new() -> std::result::Result<Arc<dyn Hypervisor>, HypervisorError> {
|
||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ use crate::cpu;
|
|||||||
use crate::cpu::Vcpu;
|
use crate::cpu::Vcpu;
|
||||||
use crate::hypervisor;
|
use crate::hypervisor;
|
||||||
use crate::vec_with_array_field;
|
use crate::vec_with_array_field;
|
||||||
use crate::vm::{self, VmmOps};
|
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
||||||
pub use mshv_bindings::*;
|
pub use mshv_bindings::*;
|
||||||
pub use mshv_ioctls::IoEventAddress;
|
pub use mshv_ioctls::IoEventAddress;
|
||||||
use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd};
|
use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use vm::DataMatch;
|
use vm::DataMatch;
|
||||||
@@ -122,7 +122,7 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
fd: vm_fd,
|
fd: vm_fd,
|
||||||
msrs,
|
msrs,
|
||||||
hv_state: hv_state_init(),
|
hv_state: hv_state_init(),
|
||||||
vmmops: None,
|
vm_ops: None,
|
||||||
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Retrieve the list of MSRs supported by KVM.
|
/// Retrieve the list of MSRs supported by MSHV.
|
||||||
///
|
///
|
||||||
fn get_msr_list(&self) -> hypervisor::Result<MsrList> {
|
fn get_msr_list(&self) -> hypervisor::Result<MsrList> {
|
||||||
self.mshv
|
self.mshv
|
||||||
@@ -151,7 +151,7 @@ pub struct MshvVcpu {
|
|||||||
cpuid: CpuId,
|
cpuid: CpuId,
|
||||||
msrs: MsrEntries,
|
msrs: MsrEntries,
|
||||||
hv_state: Arc<RwLock<HvState>>, // Mshv State
|
hv_state: Arc<RwLock<HvState>>, // Mshv State
|
||||||
vmmops: Option<Arc<dyn vm::VmmOps>>,
|
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of Vcpu trait for Microsoft Hypervisor
|
/// Implementation of Vcpu trait for Microsoft Hypervisor
|
||||||
@@ -355,14 +355,14 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
|
|
||||||
if is_write {
|
if is_write {
|
||||||
let data = (info.rax as u32).to_le_bytes();
|
let data = (info.rax as u32).to_le_bytes();
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
vmmops
|
vm_ops
|
||||||
.pio_write(port.into(), &data[0..len])
|
.pio_write(port.into(), &data[0..len])
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(vmmops) = &self.vmmops {
|
if let Some(vm_ops) = &self.vm_ops {
|
||||||
vmmops
|
vm_ops
|
||||||
.pio_read(port.into(), &mut data[0..len])
|
.pio_read(port.into(), &mut data[0..len])
|
||||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||||
}
|
}
|
||||||
@@ -655,9 +655,9 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
|
|||||||
gpa
|
gpa
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(vmmops) = &self.vcpu.vmmops {
|
if let Some(vm_ops) = &self.vcpu.vm_ops {
|
||||||
if vmmops.guest_mem_read(gpa, data).is_err() {
|
if vm_ops.guest_mem_read(gpa, data).is_err() {
|
||||||
vmmops
|
vm_ops
|
||||||
.mmio_read(gpa, data)
|
.mmio_read(gpa, data)
|
||||||
.map_err(|e| PlatformError::MemoryReadFailure(e.into()))?;
|
.map_err(|e| PlatformError::MemoryReadFailure(e.into()))?;
|
||||||
}
|
}
|
||||||
@@ -675,9 +675,9 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
|
|||||||
gpa
|
gpa
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(vmmops) = &self.vcpu.vmmops {
|
if let Some(vm_ops) = &self.vcpu.vm_ops {
|
||||||
if vmmops.guest_mem_write(gpa, data).is_err() {
|
if vm_ops.guest_mem_write(gpa, data).is_err() {
|
||||||
vmmops
|
vm_ops
|
||||||
.mmio_write(gpa, data)
|
.mmio_write(gpa, data)
|
||||||
.map_err(|e| PlatformError::MemoryWriteFailure(e.into()))?;
|
.map_err(|e| PlatformError::MemoryWriteFailure(e.into()))?;
|
||||||
}
|
}
|
||||||
@@ -746,7 +746,7 @@ pub struct MshvVm {
|
|||||||
msrs: MsrEntries,
|
msrs: MsrEntries,
|
||||||
// Hypervisor State
|
// Hypervisor State
|
||||||
hv_state: Arc<RwLock<HvState>>,
|
hv_state: Arc<RwLock<HvState>>,
|
||||||
vmmops: Option<Arc<dyn vm::VmmOps>>,
|
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||||
dirty_log_slots: Arc<RwLock<HashMap<u64, MshvDirtyLogSlot>>>,
|
dirty_log_slots: Arc<RwLock<HashMap<u64, MshvDirtyLogSlot>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +816,7 @@ impl vm::Vm for MshvVm {
|
|||||||
fn create_vcpu(
|
fn create_vcpu(
|
||||||
&self,
|
&self,
|
||||||
id: u8,
|
id: u8,
|
||||||
vmmops: Option<Arc<dyn VmmOps>>,
|
vm_ops: Option<Arc<dyn VmOps>>,
|
||||||
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
||||||
let vcpu_fd = self
|
let vcpu_fd = self
|
||||||
.fd
|
.fd
|
||||||
@@ -828,7 +828,7 @@ impl vm::Vm for MshvVm {
|
|||||||
cpuid: CpuId::new(1).unwrap(),
|
cpuid: CpuId::new(1).unwrap(),
|
||||||
msrs: self.msrs.clone(),
|
msrs: self.msrs.clone(),
|
||||||
hv_state: self.hv_state.clone(),
|
hv_state: self.hv_state.clone(),
|
||||||
vmmops,
|
vm_ops,
|
||||||
};
|
};
|
||||||
Ok(Arc::new(vcpu))
|
Ok(Arc::new(vcpu))
|
||||||
}
|
}
|
||||||
@@ -957,6 +957,27 @@ impl vm::Vm for MshvVm {
|
|||||||
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
|
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a routing entry
|
||||||
|
///
|
||||||
|
fn make_routing_entry(
|
||||||
|
&self,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> mshv_msi_routing_entry {
|
||||||
|
match config {
|
||||||
|
InterruptSourceConfig::MsiIrq(cfg) => mshv_msi_routing_entry {
|
||||||
|
gsi,
|
||||||
|
address_lo: cfg.low_addr,
|
||||||
|
address_hi: cfg.high_addr,
|
||||||
|
data: cfg.data,
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
|
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
|
||||||
let mut msi_routing =
|
let mut msi_routing =
|
||||||
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
||||||
@@ -1027,6 +1048,3 @@ impl vm::Vm for MshvVm {
|
|||||||
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
|
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub use hv_cpuid_entry as CpuIdEntry;
|
|
||||||
|
|
||||||
pub const CPUID_FLAG_VALID_INDEX: u32 = 0;
|
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Export generically-named wrappers of mshv_bindings for Unix-based platforms
|
/// Export generically-named wrappers of mshv_bindings for Unix-based platforms
|
||||||
///
|
///
|
||||||
pub use {
|
pub use {
|
||||||
|
mshv_bindings::hv_cpuid_entry as CpuIdEntry,
|
||||||
mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry,
|
mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry,
|
||||||
mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
||||||
mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState,
|
mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState,
|
||||||
@@ -25,6 +26,8 @@ pub use {
|
|||||||
mshv_bindings::Xcrs as ExtendedControlRegisters,
|
mshv_bindings::Xcrs as ExtendedControlRegisters,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const CPUID_FLAG_VALID_INDEX: u32 = 0;
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct VcpuMshvState {
|
pub struct VcpuMshvState {
|
||||||
pub msrs: MsrEntries,
|
pub msrs: MsrEntries,
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
use crate::aarch64::VcpuInit;
|
use crate::aarch64::VcpuInit;
|
||||||
use crate::cpu::Vcpu;
|
use crate::cpu::Vcpu;
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
|
#[cfg(feature = "kvm")]
|
||||||
|
use crate::kvm::KvmVmState as VmState;
|
||||||
|
#[cfg(feature = "mshv")]
|
||||||
|
use crate::mshv::HvState as VmState;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
use crate::x86_64::CpuId;
|
use crate::x86_64::CpuId;
|
||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
use crate::ClockData;
|
use crate::ClockData;
|
||||||
use crate::CreateDevice;
|
use crate::CreateDevice;
|
||||||
#[cfg(feature = "mshv")]
|
|
||||||
use crate::HvState as VmState;
|
|
||||||
#[cfg(feature = "kvm")]
|
|
||||||
use crate::KvmVmState as VmState;
|
|
||||||
use crate::{IoEventAddress, IrqRoutingEntry, MemoryRegion};
|
use crate::{IoEventAddress, IrqRoutingEntry, MemoryRegion};
|
||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
use kvm_ioctls::Cap;
|
use kvm_ioctls::Cap;
|
||||||
@@ -216,6 +216,39 @@ pub enum HypervisorVmError {
|
|||||||
///
|
///
|
||||||
pub type Result<T> = std::result::Result<T, HypervisorVmError>;
|
pub type Result<T> = std::result::Result<T, HypervisorVmError>;
|
||||||
|
|
||||||
|
/// Configuration data for legacy interrupts.
|
||||||
|
///
|
||||||
|
/// On x86 platforms, legacy interrupts means those interrupts routed through PICs or IOAPICs.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct LegacyIrqSourceConfig {
|
||||||
|
pub irqchip: u32,
|
||||||
|
pub pin: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configuration data for MSI/MSI-X interrupts.
|
||||||
|
///
|
||||||
|
/// On x86 platforms, these interrupts are vectors delivered directly to the LAPIC.
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct MsiIrqSourceConfig {
|
||||||
|
/// High address to delivery message signaled interrupt.
|
||||||
|
pub high_addr: u32,
|
||||||
|
/// Low address to delivery message signaled interrupt.
|
||||||
|
pub low_addr: u32,
|
||||||
|
/// Data to write to delivery message signaled interrupt.
|
||||||
|
pub data: u32,
|
||||||
|
/// Unique ID of the device to delivery message signaled interrupt.
|
||||||
|
pub devid: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configuration data for an interrupt source.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum InterruptSourceConfig {
|
||||||
|
/// Configuration data for Legacy interrupts.
|
||||||
|
LegacyIrq(LegacyIrqSourceConfig),
|
||||||
|
/// Configuration data for PciMsi, PciMsix and generic MSI interrupts.
|
||||||
|
MsiIrq(MsiIrqSourceConfig),
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trait to represent a Vm
|
/// Trait to represent a Vm
|
||||||
///
|
///
|
||||||
@@ -235,7 +268,7 @@ pub trait Vm: Send + Sync {
|
|||||||
/// Unregister an event that will, when signaled, trigger the `gsi` IRQ.
|
/// Unregister an event that will, when signaled, trigger the `gsi` IRQ.
|
||||||
fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>;
|
fn unregister_irqfd(&self, fd: &EventFd, gsi: u32) -> Result<()>;
|
||||||
/// Creates a new KVM vCPU file descriptor and maps the memory corresponding
|
/// Creates a new KVM vCPU file descriptor and maps the memory corresponding
|
||||||
fn create_vcpu(&self, id: u8, vmmops: Option<Arc<dyn VmmOps>>) -> Result<Arc<dyn Vcpu>>;
|
fn create_vcpu(&self, id: u8, vm_ops: Option<Arc<dyn VmOps>>) -> Result<Arc<dyn Vcpu>>;
|
||||||
/// Registers an event to be signaled whenever a certain address is written to.
|
/// Registers an event to be signaled whenever a certain address is written to.
|
||||||
fn register_ioevent(
|
fn register_ioevent(
|
||||||
&self,
|
&self,
|
||||||
@@ -245,6 +278,8 @@ pub trait Vm: Send + Sync {
|
|||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
/// Unregister an event from a certain address it has been previously registered to.
|
/// Unregister an event from a certain address it has been previously registered to.
|
||||||
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>;
|
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>;
|
||||||
|
// Construct a routing entry
|
||||||
|
fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry;
|
||||||
/// Sets the GSI routing table entries, overwriting any previously set
|
/// Sets the GSI routing table entries, overwriting any previously set
|
||||||
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> Result<()>;
|
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> Result<()>;
|
||||||
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region
|
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region
|
||||||
@@ -309,7 +344,7 @@ pub trait Vm: Send + Sync {
|
|||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VmmOps: Send + Sync {
|
pub trait VmOps: Send + Sync {
|
||||||
fn guest_mem_write(&self, gpa: u64, buf: &[u8]) -> Result<usize>;
|
fn guest_mem_write(&self, gpa: u64, buf: &[u8]) -> Result<usize>;
|
||||||
fn guest_mem_read(&self, gpa: u64, buf: &mut [u8]) -> Result<usize>;
|
fn guest_mem_read(&self, gpa: u64, buf: &mut [u8]) -> Result<usize>;
|
||||||
fn mmio_read(&self, gpa: u64, data: &mut [u8]) -> Result<()>;
|
fn mmio_read(&self, gpa: u64, data: &mut [u8]) -> Result<()>;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "net_gen"
|
name = "net_gen"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
@@ -2,25 +2,25 @@
|
|||||||
name = "net_util"
|
name = "net_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
getrandom = "0.2"
|
getrandom = "0.2"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
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.136"
|
serde = "1.0.137"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = "0.1.0"
|
virtio-bindings = "0.1.0"
|
||||||
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio", branch = "main" }
|
virtio-queue = "0.3.0"
|
||||||
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.8.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
pnet = "0.29.0"
|
pnet = "0.30.0"
|
||||||
serde_json = "1.0.79"
|
serde_json = "1.0.81"
|
||||||
|
|||||||
@@ -60,97 +60,103 @@ impl CtrlQueue {
|
|||||||
&mut self,
|
&mut self,
|
||||||
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
||||||
) -> Result<bool> {
|
) -> Result<()> {
|
||||||
let mut used_desc_heads = Vec::new();
|
let mut used_desc_heads = Vec::new();
|
||||||
for mut desc_chain in queue.iter().map_err(Error::QueueIterator)? {
|
loop {
|
||||||
let ctrl_desc = desc_chain.next().ok_or(Error::NoControlHeaderDescriptor)?;
|
for mut desc_chain in queue.iter().map_err(Error::QueueIterator)? {
|
||||||
|
let ctrl_desc = desc_chain.next().ok_or(Error::NoControlHeaderDescriptor)?;
|
||||||
|
|
||||||
let ctrl_hdr: ControlHeader = desc_chain
|
let ctrl_hdr: ControlHeader = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
.read_obj(
|
.read_obj(
|
||||||
ctrl_desc
|
ctrl_desc
|
||||||
.addr()
|
.addr()
|
||||||
.translate(access_platform, ctrl_desc.len() as usize),
|
.translate_gva(access_platform, ctrl_desc.len() as usize),
|
||||||
)
|
)
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
let data_desc = desc_chain.next().ok_or(Error::NoDataDescriptor)?;
|
let data_desc = desc_chain.next().ok_or(Error::NoDataDescriptor)?;
|
||||||
|
|
||||||
let data_desc_addr = data_desc
|
let data_desc_addr = data_desc
|
||||||
.addr()
|
.addr()
|
||||||
.translate(access_platform, data_desc.len() as usize);
|
.translate_gva(access_platform, data_desc.len() as usize);
|
||||||
|
|
||||||
let status_desc = desc_chain.next().ok_or(Error::NoStatusDescriptor)?;
|
let status_desc = desc_chain.next().ok_or(Error::NoStatusDescriptor)?;
|
||||||
|
|
||||||
let ok = match u32::from(ctrl_hdr.class) {
|
let ok = match u32::from(ctrl_hdr.class) {
|
||||||
VIRTIO_NET_CTRL_MQ => {
|
VIRTIO_NET_CTRL_MQ => {
|
||||||
let queue_pairs = desc_chain
|
let queue_pairs = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
.read_obj::<u16>(data_desc_addr)
|
.read_obj::<u16>(data_desc_addr)
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
|
||||||
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
false
|
false
|
||||||
} else if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
|
} else if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
|
||||||
|| (queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
|
|| (queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
|
||||||
{
|
{
|
||||||
warn!("Number of MQ pairs out of range: {}", queue_pairs);
|
warn!("Number of MQ pairs out of range: {}", queue_pairs);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
info!("Number of MQ pairs requested: {}", queue_pairs);
|
info!("Number of MQ pairs requested: {}", queue_pairs);
|
||||||
true
|
true
|
||||||
}
|
|
||||||
}
|
|
||||||
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
|
||||||
let features = desc_chain
|
|
||||||
.memory()
|
|
||||||
.read_obj::<u64>(data_desc_addr)
|
|
||||||
.map_err(Error::GuestMemory)?;
|
|
||||||
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
|
|
||||||
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
let mut ok = true;
|
|
||||||
for tap in self.taps.iter_mut() {
|
|
||||||
info!("Reprogramming tap offload with features: {}", features);
|
|
||||||
tap.set_offload(virtio_features_to_tap_offload(features))
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("Error programming tap offload: {:?}", e);
|
|
||||||
ok = false
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
ok
|
|
||||||
}
|
}
|
||||||
}
|
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
||||||
_ => {
|
let features = desc_chain
|
||||||
warn!("Unsupported command {:?}", ctrl_hdr);
|
.memory()
|
||||||
false
|
.read_obj::<u64>(data_desc_addr)
|
||||||
}
|
.map_err(Error::GuestMemory)?;
|
||||||
};
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
|
||||||
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let mut ok = true;
|
||||||
|
for tap in self.taps.iter_mut() {
|
||||||
|
info!("Reprogramming tap offload with features: {}", features);
|
||||||
|
tap.set_offload(virtio_features_to_tap_offload(features))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Error programming tap offload: {:?}", e);
|
||||||
|
ok = false
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("Unsupported command {:?}", ctrl_hdr);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
desc_chain
|
desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
.write_obj(
|
.write_obj(
|
||||||
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
|
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
|
||||||
status_desc
|
status_desc
|
||||||
.addr()
|
.addr()
|
||||||
.translate(access_platform, status_desc.len() as usize),
|
.translate_gva(access_platform, status_desc.len() as usize),
|
||||||
)
|
)
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
let len = ctrl_desc.len() + data_desc.len() + status_desc.len();
|
let len = ctrl_desc.len() + data_desc.len() + status_desc.len();
|
||||||
used_desc_heads.push((desc_chain.head_index(), len));
|
used_desc_heads.push((desc_chain.head_index(), len));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (desc_index, len) in used_desc_heads.iter() {
|
for (desc_index, len) in used_desc_heads.iter() {
|
||||||
queue
|
queue
|
||||||
.add_used(*desc_index, *len)
|
.add_used(*desc_index, *len)
|
||||||
.map_err(Error::QueueAddUsed)?;
|
.map_err(Error::QueueAddUsed)?;
|
||||||
queue
|
}
|
||||||
|
|
||||||
|
if !queue
|
||||||
.enable_notification()
|
.enable_notification()
|
||||||
.map_err(Error::QueueEnableNotification)?;
|
.map_err(Error::QueueEnableNotification)?
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(!used_desc_heads.is_empty())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ impl TxVirtio {
|
|||||||
|
|
||||||
let mut iovecs = Vec::new();
|
let mut iovecs = Vec::new();
|
||||||
while let Some(desc) = next_desc {
|
while let Some(desc) = next_desc {
|
||||||
let desc_addr = desc.addr().translate(access_platform, desc.len() as usize);
|
let desc_addr = desc
|
||||||
|
.addr()
|
||||||
|
.translate_gva(access_platform, desc.len() as usize);
|
||||||
if !desc.is_write_only() && desc.len() > 0 {
|
if !desc.is_write_only() && desc.len() > 0 {
|
||||||
let buf = desc_chain
|
let buf = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
@@ -130,9 +132,12 @@ impl TxVirtio {
|
|||||||
queue
|
queue
|
||||||
.add_used(used_desc_head.0, used_desc_head.1)
|
.add_used(used_desc_head.0, used_desc_head.1)
|
||||||
.map_err(NetQueuePairError::QueueAddUsed)?;
|
.map_err(NetQueuePairError::QueueAddUsed)?;
|
||||||
queue
|
if !queue
|
||||||
.enable_notification()
|
.enable_notification()
|
||||||
.map_err(NetQueuePairError::QueueEnableNotification)?;
|
.map_err(NetQueuePairError::QueueEnableNotification)?
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(retry_write)
|
Ok(retry_write)
|
||||||
@@ -189,7 +194,8 @@ impl RxVirtio {
|
|||||||
let num_buffers_addr = desc_chain
|
let num_buffers_addr = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
.checked_offset(
|
.checked_offset(
|
||||||
desc.addr().translate(access_platform, desc.len() as usize),
|
desc.addr()
|
||||||
|
.translate_gva(access_platform, desc.len() as usize),
|
||||||
10,
|
10,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -197,7 +203,9 @@ impl RxVirtio {
|
|||||||
|
|
||||||
let mut iovecs = Vec::new();
|
let mut iovecs = Vec::new();
|
||||||
while let Some(desc) = next_desc {
|
while let Some(desc) = next_desc {
|
||||||
let desc_addr = desc.addr().translate(access_platform, desc.len() as usize);
|
let desc_addr = desc
|
||||||
|
.addr()
|
||||||
|
.translate_gva(access_platform, desc.len() as usize);
|
||||||
if desc.is_write_only() && desc.len() > 0 {
|
if desc.is_write_only() && desc.len() > 0 {
|
||||||
let buf = desc_chain
|
let buf = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
@@ -275,9 +283,12 @@ impl RxVirtio {
|
|||||||
queue
|
queue
|
||||||
.add_used(used_desc_head.0, used_desc_head.1)
|
.add_used(used_desc_head.0, used_desc_head.1)
|
||||||
.map_err(NetQueuePairError::QueueAddUsed)?;
|
.map_err(NetQueuePairError::QueueAddUsed)?;
|
||||||
queue
|
if !queue
|
||||||
.enable_notification()
|
.enable_notification()
|
||||||
.map_err(NetQueuePairError::QueueEnableNotification)?;
|
.map_err(NetQueuePairError::QueueEnableNotification)?
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(exhausted_descs)
|
Ok(exhausted_descs)
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ impl OptionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for option in split_commas_outside_brackets(input)?.iter() {
|
for option in split_commas_outside_brackets(input)?.iter() {
|
||||||
let parts: Vec<&str> = option.split('=').collect();
|
let parts: Vec<&str> = option.splitn(2, '=').collect();
|
||||||
|
|
||||||
match self.options.get_mut(parts[0]) {
|
match self.options.get_mut(parts[0]) {
|
||||||
None => return Err(OptionParserError::UnknownOption(parts[0].to_owned())),
|
None => return Err(OptionParserError::UnknownOption(parts[0].to_owned())),
|
||||||
@@ -313,6 +313,7 @@ impl<S: FromStr, T: TupleValue> FromStr for Tuple<S, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct StringList(pub Vec<String>);
|
pub struct StringList(pub Vec<String>);
|
||||||
|
|
||||||
pub enum StringListParseError {
|
pub enum StringListParseError {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "pci"
|
name = "pci"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Samuel Ortiz <sameo@linux.intel.com>"]
|
authors = ["Samuel Ortiz <sameo@linux.intel.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
@@ -10,22 +10,21 @@ kvm = ["vfio-ioctls/kvm"]
|
|||||||
mshv = ["vfio-ioctls/mshv"]
|
mshv = ["vfio-ioctls/mshv"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.55"
|
anyhow = "1.0.57"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
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 }
|
||||||
vfio_user = { path = "../vfio_user" }
|
vfio_user = { path = "../vfio_user" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
serde = "1.0.136"
|
serde = { version="1.0.137", features=["derive"] }
|
||||||
serde_derive = "1.0.136"
|
thiserror = "1.0.31"
|
||||||
thiserror = "1.0.30"
|
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
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.7.0"
|
vm-memory = "0.8.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
|
|
||||||
[dependencies.vfio-bindings]
|
[dependencies.vfio-bindings]
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ use crate::configuration::{
|
|||||||
PciBarRegionType, PciBridgeSubclass, PciClassCode, PciConfiguration, PciHeaderType,
|
PciBarRegionType, PciBridgeSubclass, PciClassCode, PciConfiguration, PciHeaderType,
|
||||||
};
|
};
|
||||||
use crate::device::{DeviceRelocation, Error as PciDeviceError, PciDevice};
|
use crate::device::{DeviceRelocation, Error as PciDeviceError, PciDevice};
|
||||||
|
use crate::PciBarConfiguration;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use vm_device::{Bus, BusDevice};
|
use vm_device::{Bus, BusDevice};
|
||||||
use vm_memory::{Address, GuestAddress, GuestUsize};
|
|
||||||
|
|
||||||
const VENDOR_ID_INTEL: u16 = 0x8086;
|
const VENDOR_ID_INTEL: u16 = 0x8086;
|
||||||
const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57;
|
const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57;
|
||||||
@@ -88,6 +88,10 @@ impl PciDevice for PciRoot {
|
|||||||
fn as_any(&mut self) -> &mut dyn Any {
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PciBus {
|
pub struct PciBus {
|
||||||
@@ -118,21 +122,21 @@ impl PciBus {
|
|||||||
dev: Arc<Mutex<dyn BusDevice>>,
|
dev: Arc<Mutex<dyn BusDevice>>,
|
||||||
#[cfg(target_arch = "x86_64")] io_bus: &Bus,
|
#[cfg(target_arch = "x86_64")] io_bus: &Bus,
|
||||||
mmio_bus: &Bus,
|
mmio_bus: &Bus,
|
||||||
bars: Vec<(GuestAddress, GuestUsize, PciBarRegionType)>,
|
bars: Vec<PciBarConfiguration>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (address, size, type_) in bars {
|
for bar in bars {
|
||||||
match type_ {
|
match bar.region_type() {
|
||||||
PciBarRegionType::IoRegion => {
|
PciBarRegionType::IoRegion => {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
io_bus
|
io_bus
|
||||||
.insert(dev.clone(), address.raw_value(), size)
|
.insert(dev.clone(), bar.addr(), bar.size())
|
||||||
.map_err(PciRootError::PioInsert)?;
|
.map_err(PciRootError::PioInsert)?;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
error!("I/O region is not supported");
|
error!("I/O region is not supported");
|
||||||
}
|
}
|
||||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
|
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
|
||||||
mmio_bus
|
mmio_bus
|
||||||
.insert(dev.clone(), address.raw_value(), size)
|
.insert(dev.clone(), bar.addr(), bar.size())
|
||||||
.map_err(PciRootError::MmioInsert)?;
|
.map_err(PciRootError::MmioInsert)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use std::fmt::{self, Display};
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
|
use vm_device::PciBarType;
|
||||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||||
|
|
||||||
// The number of 32bit registers in the config space, 4096 bytes.
|
// The number of 32bit registers in the config space, 4096 bytes.
|
||||||
@@ -18,6 +19,7 @@ const STATUS_REG: usize = 1;
|
|||||||
const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000;
|
const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000;
|
||||||
const BAR0_REG: usize = 4;
|
const BAR0_REG: usize = 4;
|
||||||
const ROM_BAR_REG: usize = 12;
|
const ROM_BAR_REG: usize = 12;
|
||||||
|
const ROM_BAR_IDX: usize = 6;
|
||||||
const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc;
|
const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc;
|
||||||
const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
|
const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
|
||||||
const ROM_BAR_ADDR_MASK: u32 = 0xffff_f800;
|
const ROM_BAR_ADDR_MASK: u32 = 0xffff_f800;
|
||||||
@@ -326,17 +328,48 @@ pub enum PciBarRegionType {
|
|||||||
Memory64BitRegion = 0x04,
|
Memory64BitRegion = 0x04,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<PciBarType> for PciBarRegionType {
|
||||||
|
fn from(type_: PciBarType) -> Self {
|
||||||
|
match type_ {
|
||||||
|
PciBarType::Io => PciBarRegionType::IoRegion,
|
||||||
|
PciBarType::Mmio32 => PciBarRegionType::Memory32BitRegion,
|
||||||
|
PciBarType::Mmio64 => PciBarRegionType::Memory64BitRegion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::from_over_into)]
|
||||||
|
impl Into<PciBarType> for PciBarRegionType {
|
||||||
|
fn into(self) -> PciBarType {
|
||||||
|
match self {
|
||||||
|
PciBarRegionType::IoRegion => PciBarType::Io,
|
||||||
|
PciBarRegionType::Memory32BitRegion => PciBarType::Mmio32,
|
||||||
|
PciBarRegionType::Memory64BitRegion => PciBarType::Mmio64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum PciBarPrefetchable {
|
pub enum PciBarPrefetchable {
|
||||||
NotPrefetchable = 0,
|
NotPrefetchable = 0,
|
||||||
Prefetchable = 0x08,
|
Prefetchable = 0x08,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::from_over_into)]
|
||||||
|
impl Into<bool> for PciBarPrefetchable {
|
||||||
|
fn into(self) -> bool {
|
||||||
|
match self {
|
||||||
|
PciBarPrefetchable::NotPrefetchable => false,
|
||||||
|
PciBarPrefetchable::Prefetchable => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct PciBarConfiguration {
|
pub struct PciBarConfiguration {
|
||||||
addr: u64,
|
addr: u64,
|
||||||
size: u64,
|
size: u64,
|
||||||
reg_idx: usize,
|
idx: usize,
|
||||||
region_type: PciBarRegionType,
|
region_type: PciBarRegionType,
|
||||||
prefetchable: PciBarPrefetchable,
|
prefetchable: PciBarPrefetchable,
|
||||||
}
|
}
|
||||||
@@ -556,22 +589,23 @@ impl PciConfiguration {
|
|||||||
|
|
||||||
/// Adds a region specified by `config`. Configures the specified BAR(s) to
|
/// Adds a region specified by `config`. Configures the specified BAR(s) to
|
||||||
/// report this region and size to the guest kernel. Enforces a few constraints
|
/// report this region and size to the guest kernel. Enforces a few constraints
|
||||||
/// (i.e, region size must be power of two, register not already used). Returns 'None' on
|
/// (i.e, region size must be power of two, register not already used).
|
||||||
/// failure all, `Some(BarIndex)` on success.
|
pub fn add_pci_bar(&mut self, config: &PciBarConfiguration) -> Result<()> {
|
||||||
pub fn add_pci_bar(&mut self, config: &PciBarConfiguration) -> Result<usize> {
|
let bar_idx = config.idx;
|
||||||
if self.bars[config.reg_idx].used {
|
let reg_idx = BAR0_REG + bar_idx;
|
||||||
return Err(Error::BarInUse(config.reg_idx));
|
|
||||||
|
if self.bars[bar_idx].used {
|
||||||
|
return Err(Error::BarInUse(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.size.count_ones() != 1 {
|
if config.size.count_ones() != 1 {
|
||||||
return Err(Error::BarSizeInvalid(config.size));
|
return Err(Error::BarSizeInvalid(config.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.reg_idx >= NUM_BAR_REGS {
|
if bar_idx >= NUM_BAR_REGS {
|
||||||
return Err(Error::BarInvalid(config.reg_idx));
|
return Err(Error::BarInvalid(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
let bar_idx = BAR0_REG + config.reg_idx;
|
|
||||||
let end_addr = config
|
let end_addr = config
|
||||||
.addr
|
.addr
|
||||||
.checked_add(config.size - 1)
|
.checked_add(config.size - 1)
|
||||||
@@ -584,20 +618,20 @@ impl PciConfiguration {
|
|||||||
|
|
||||||
// Encode the BAR size as expected by the software running in
|
// Encode the BAR size as expected by the software running in
|
||||||
// the guest.
|
// the guest.
|
||||||
self.bars[config.reg_idx].size =
|
self.bars[bar_idx].size =
|
||||||
encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?;
|
encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?;
|
||||||
}
|
}
|
||||||
PciBarRegionType::Memory64BitRegion => {
|
PciBarRegionType::Memory64BitRegion => {
|
||||||
if config.reg_idx + 1 >= NUM_BAR_REGS {
|
if bar_idx + 1 >= NUM_BAR_REGS {
|
||||||
return Err(Error::BarInvalid64(config.reg_idx));
|
return Err(Error::BarInvalid64(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
if end_addr > u64::max_value() {
|
if end_addr > u64::max_value() {
|
||||||
return Err(Error::BarAddressInvalid(config.addr, config.size));
|
return Err(Error::BarAddressInvalid(config.addr, config.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.bars[config.reg_idx + 1].used {
|
if self.bars[bar_idx + 1].used {
|
||||||
return Err(Error::BarInUse64(config.reg_idx));
|
return Err(Error::BarInUse64(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode the BAR size as expected by the software running in
|
// Encode the BAR size as expected by the software running in
|
||||||
@@ -605,12 +639,12 @@ impl PciConfiguration {
|
|||||||
let (bar_size_hi, bar_size_lo) =
|
let (bar_size_hi, bar_size_lo) =
|
||||||
encode_64_bits_bar_size(config.size).ok_or(Error::Encode64BarSize)?;
|
encode_64_bits_bar_size(config.size).ok_or(Error::Encode64BarSize)?;
|
||||||
|
|
||||||
self.registers[bar_idx + 1] = (config.addr >> 32) as u32;
|
self.registers[reg_idx + 1] = (config.addr >> 32) as u32;
|
||||||
self.writable_bits[bar_idx + 1] = 0xffff_ffff;
|
self.writable_bits[reg_idx + 1] = 0xffff_ffff;
|
||||||
self.bars[config.reg_idx + 1].addr = self.registers[bar_idx + 1];
|
self.bars[bar_idx + 1].addr = self.registers[reg_idx + 1];
|
||||||
self.bars[config.reg_idx].size = bar_size_lo;
|
self.bars[bar_idx].size = bar_size_lo;
|
||||||
self.bars[config.reg_idx + 1].size = bar_size_hi;
|
self.bars[bar_idx + 1].size = bar_size_hi;
|
||||||
self.bars[config.reg_idx + 1].used = true;
|
self.bars[bar_idx + 1].used = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,26 +656,30 @@ impl PciConfiguration {
|
|||||||
PciBarRegionType::IoRegion => (BAR_IO_ADDR_MASK, config.region_type as u32),
|
PciBarRegionType::IoRegion => (BAR_IO_ADDR_MASK, config.region_type as u32),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.registers[bar_idx] = ((config.addr as u32) & mask) | lower_bits;
|
self.registers[reg_idx] = ((config.addr as u32) & mask) | lower_bits;
|
||||||
self.writable_bits[bar_idx] = mask;
|
self.writable_bits[reg_idx] = mask;
|
||||||
self.bars[config.reg_idx].addr = self.registers[bar_idx];
|
self.bars[bar_idx].addr = self.registers[reg_idx];
|
||||||
self.bars[config.reg_idx].used = true;
|
self.bars[bar_idx].used = true;
|
||||||
self.bars[config.reg_idx].r#type = Some(config.region_type);
|
self.bars[bar_idx].r#type = Some(config.region_type);
|
||||||
Ok(config.reg_idx)
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds rom expansion BAR.
|
/// Adds rom expansion BAR.
|
||||||
pub fn add_pci_rom_bar(&mut self, config: &PciBarConfiguration, active: u32) -> Result<usize> {
|
pub fn add_pci_rom_bar(&mut self, config: &PciBarConfiguration, active: u32) -> Result<()> {
|
||||||
|
let bar_idx = config.idx;
|
||||||
|
let reg_idx = ROM_BAR_REG;
|
||||||
|
|
||||||
if self.rom_bar_used {
|
if self.rom_bar_used {
|
||||||
return Err(Error::RomBarInUse(config.reg_idx));
|
return Err(Error::RomBarInUse(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.size.count_ones() != 1 {
|
if config.size.count_ones() != 1 {
|
||||||
return Err(Error::RomBarSizeInvalid(config.size));
|
return Err(Error::RomBarSizeInvalid(config.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.reg_idx != ROM_BAR_REG {
|
if bar_idx != ROM_BAR_IDX {
|
||||||
return Err(Error::RomBarInvalid(config.reg_idx));
|
return Err(Error::RomBarInvalid(bar_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
let end_addr = config
|
let end_addr = config
|
||||||
@@ -653,13 +691,14 @@ impl PciConfiguration {
|
|||||||
return Err(Error::RomBarAddressInvalid(config.addr, config.size));
|
return Err(Error::RomBarAddressInvalid(config.addr, config.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.registers[config.reg_idx] = (config.addr as u32) | active;
|
self.registers[reg_idx] = (config.addr as u32) | active;
|
||||||
self.writable_bits[config.reg_idx] = ROM_BAR_ADDR_MASK;
|
self.writable_bits[reg_idx] = ROM_BAR_ADDR_MASK;
|
||||||
self.rom_bar_addr = self.registers[config.reg_idx];
|
self.rom_bar_addr = self.registers[reg_idx];
|
||||||
self.rom_bar_size =
|
self.rom_bar_size =
|
||||||
encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?;
|
encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?;
|
||||||
self.rom_bar_used = true;
|
self.rom_bar_used = true;
|
||||||
Ok(config.reg_idx)
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the address of the given BAR region.
|
/// Returns the address of the given BAR region.
|
||||||
@@ -911,7 +950,7 @@ impl Snapshottable for PciConfiguration {
|
|||||||
impl Default for PciBarConfiguration {
|
impl Default for PciBarConfiguration {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
PciBarConfiguration {
|
PciBarConfiguration {
|
||||||
reg_idx: 0,
|
idx: 0,
|
||||||
addr: 0,
|
addr: 0,
|
||||||
size: 0,
|
size: 0,
|
||||||
region_type: PciBarRegionType::Memory64BitRegion,
|
region_type: PciBarRegionType::Memory64BitRegion,
|
||||||
@@ -922,13 +961,13 @@ impl Default for PciBarConfiguration {
|
|||||||
|
|
||||||
impl PciBarConfiguration {
|
impl PciBarConfiguration {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
reg_idx: usize,
|
idx: usize,
|
||||||
size: u64,
|
size: u64,
|
||||||
region_type: PciBarRegionType,
|
region_type: PciBarRegionType,
|
||||||
prefetchable: PciBarPrefetchable,
|
prefetchable: PciBarPrefetchable,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
PciBarConfiguration {
|
PciBarConfiguration {
|
||||||
reg_idx,
|
idx,
|
||||||
addr: 0,
|
addr: 0,
|
||||||
size,
|
size,
|
||||||
region_type,
|
region_type,
|
||||||
@@ -937,8 +976,8 @@ impl PciBarConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn set_register_index(mut self, reg_idx: usize) -> Self {
|
pub fn set_index(mut self, idx: usize) -> Self {
|
||||||
self.reg_idx = reg_idx;
|
self.idx = idx;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,15 +993,31 @@ impl PciBarConfiguration {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size(&self) -> u64 {
|
|
||||||
self.size
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn set_region_type(mut self, region_type: PciBarRegionType) -> Self {
|
pub fn set_region_type(mut self, region_type: PciBarRegionType) -> Self {
|
||||||
self.region_type = region_type;
|
self.region_type = region_type;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn idx(&self) -> usize {
|
||||||
|
self.idx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addr(&self) -> u64 {
|
||||||
|
self.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn region_type(&self) -> PciBarRegionType {
|
||||||
|
self.region_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prefetchable(&self) -> PciBarPrefetchable {
|
||||||
|
self.prefetchable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
use crate::configuration::{self, PciBarRegionType};
|
use crate::configuration::{self, PciBarRegionType};
|
||||||
|
use crate::PciBarConfiguration;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use std::{self, io, result};
|
use std::{self, io, result};
|
||||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::BusDevice;
|
use vm_device::{BusDevice, Resource};
|
||||||
use vm_memory::{GuestAddress, GuestUsize};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -19,6 +19,8 @@ pub enum Error {
|
|||||||
IoAllocationFailed(u64),
|
IoAllocationFailed(u64),
|
||||||
/// Registering an IO BAR failed.
|
/// Registering an IO BAR failed.
|
||||||
IoRegistrationFailed(u64, configuration::Error),
|
IoRegistrationFailed(u64, configuration::Error),
|
||||||
|
/// Expected resource not found.
|
||||||
|
MissingResource,
|
||||||
}
|
}
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ impl Display for Error {
|
|||||||
IoRegistrationFailed(addr, e) => {
|
IoRegistrationFailed(addr, e) => {
|
||||||
write!(f, "failed to register an IO BAR, addr={} err={}", addr, e)
|
write!(f, "failed to register an IO BAR, addr={} err={}", addr, e)
|
||||||
}
|
}
|
||||||
|
MissingResource => write!(f, "failed to find expected resource"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +56,8 @@ pub trait PciDevice: BusDevice {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_allocator: &Arc<Mutex<SystemAllocator>>,
|
_allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
_mmio_allocator: &mut AddressAllocator,
|
_mmio_allocator: &mut AddressAllocator,
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>> {
|
_resources: Option<Vec<Resource>>,
|
||||||
|
) -> Result<Vec<PciBarConfiguration>> {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +107,9 @@ pub trait PciDevice: BusDevice {
|
|||||||
/// Provides a mutable reference to the Any trait. This is useful to let
|
/// Provides a mutable reference to the Any trait. This is useful to let
|
||||||
/// the caller have access to the underlying type behind the trait.
|
/// the caller have access to the underlying type behind the trait.
|
||||||
fn as_any(&mut self) -> &mut dyn Any;
|
fn as_any(&mut self) -> &mut dyn Any;
|
||||||
|
|
||||||
|
/// Optionally returns a unique identifier.
|
||||||
|
fn id(&self) -> Option<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait defines a set of functions which can be triggered whenever a
|
/// This trait defines a set of functions which can be triggered whenever a
|
||||||
|
|||||||
@@ -3,11 +3,17 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
use std::io;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use thiserror::Error;
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||||
};
|
};
|
||||||
|
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||||
|
|
||||||
// MSI control masks
|
// MSI control masks
|
||||||
const MSI_CTL_ENABLE: u16 = 0x1;
|
const MSI_CTL_ENABLE: u16 = 0x1;
|
||||||
@@ -32,7 +38,15 @@ pub fn msi_num_enabled_vectors(msg_ctl: u16) -> usize {
|
|||||||
1 << field
|
1 << field
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Error, Debug)]
|
||||||
|
enum Error {
|
||||||
|
#[error("Failed enabling the interrupt route: {0}")]
|
||||||
|
EnableInterruptRoute(io::Error),
|
||||||
|
#[error("Failed updating the interrupt route: {0}")]
|
||||||
|
UpdateInterruptRoute(io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, Versionize)]
|
||||||
pub struct MsiCap {
|
pub struct MsiCap {
|
||||||
// Message Control Register
|
// Message Control Register
|
||||||
// 0: MSI enable.
|
// 0: MSI enable.
|
||||||
@@ -157,6 +171,13 @@ impl MsiCap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Versionize)]
|
||||||
|
struct MsiConfigState {
|
||||||
|
cap: MsiCap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for MsiConfigState {}
|
||||||
|
|
||||||
pub struct MsiConfig {
|
pub struct MsiConfig {
|
||||||
cap: MsiCap,
|
cap: MsiCap,
|
||||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||||
@@ -175,6 +196,39 @@ impl MsiConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> MsiConfigState {
|
||||||
|
MsiConfigState { cap: self.cap }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_state(&mut self, state: &MsiConfigState) -> Result<(), Error> {
|
||||||
|
self.cap = state.cap;
|
||||||
|
|
||||||
|
if self.enabled() {
|
||||||
|
for idx in 0..self.num_enabled_vectors() {
|
||||||
|
let config = MsiIrqSourceConfig {
|
||||||
|
high_addr: self.cap.msg_addr_hi,
|
||||||
|
low_addr: self.cap.msg_addr_lo,
|
||||||
|
data: self.cap.msg_data as u32,
|
||||||
|
devid: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interrupt_source_group
|
||||||
|
.update(
|
||||||
|
idx as InterruptIndex,
|
||||||
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
self.cap.vector_masked(idx),
|
||||||
|
)
|
||||||
|
.map_err(Error::UpdateInterruptRoute)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.interrupt_source_group
|
||||||
|
.enable()
|
||||||
|
.map_err(Error::EnableInterruptRoute)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enabled(&self) -> bool {
|
pub fn enabled(&self) -> bool {
|
||||||
self.cap.enabled()
|
self.cap.enabled()
|
||||||
}
|
}
|
||||||
@@ -201,20 +255,13 @@ impl MsiConfig {
|
|||||||
devid: 0,
|
devid: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
.interrupt_source_group
|
idx as InterruptIndex,
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
{
|
self.cap.vector_masked(idx),
|
||||||
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.cap.vector_masked(idx) {
|
|
||||||
if let Err(e) = self.interrupt_source_group.mask(idx as InterruptIndex) {
|
|
||||||
error!("Failed masking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
} else if let Err(e) = self.interrupt_source_group.unmask(idx as InterruptIndex) {
|
|
||||||
error!("Failed unmasking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !old_enabled {
|
if !old_enabled {
|
||||||
@@ -229,3 +276,26 @@ impl MsiConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pausable for MsiConfig {}
|
||||||
|
|
||||||
|
impl Snapshottable for MsiConfig {
|
||||||
|
fn id(&self) -> String {
|
||||||
|
String::from("msi_config")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
|
Snapshot::new_from_versioned_state(&self.id(), &self.state())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||||
|
self.set_state(&snapshot.to_versioned_state(&self.id())?)
|
||||||
|
.map_err(|e| {
|
||||||
|
MigratableError::Restore(anyhow!(
|
||||||
|
"Could not restore state for {}: {:?}",
|
||||||
|
self.id(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -132,7 +132,11 @@ impl MsixConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
.update(
|
||||||
|
idx as InterruptIndex,
|
||||||
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
self.masked,
|
||||||
|
)
|
||||||
.map_err(Error::UpdateInterruptRoute)?;
|
.map_err(Error::UpdateInterruptRoute)?;
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
@@ -171,21 +175,13 @@ impl MsixConfig {
|
|||||||
devid: self.devid,
|
devid: self.devid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
.interrupt_source_group
|
idx as InterruptIndex,
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
{
|
table_entry.masked(),
|
||||||
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if table_entry.masked() {
|
|
||||||
if let Err(e) = self.interrupt_source_group.mask(idx as InterruptIndex) {
|
|
||||||
error!("Failed masking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
} else if let Err(e) = self.interrupt_source_group.unmask(idx as InterruptIndex)
|
|
||||||
{
|
|
||||||
error!("Failed unmasking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if old_enabled || !old_masked {
|
} else if old_enabled || !old_masked {
|
||||||
debug!("MSI-X disabled for device 0x{:x}", self.devid);
|
debug!("MSI-X disabled for device 0x{:x}", self.devid);
|
||||||
@@ -314,17 +310,10 @@ impl MsixConfig {
|
|||||||
if let Err(e) = self.interrupt_source_group.update(
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
index as InterruptIndex,
|
index as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
table_entry.masked(),
|
||||||
) {
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if table_entry.masked() {
|
|
||||||
if let Err(e) = self.interrupt_source_group.mask(index as InterruptIndex) {
|
|
||||||
error!("Failed masking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
} else if let Err(e) = self.interrupt_source_group.unmask(index as InterruptIndex) {
|
|
||||||
error!("Failed unmasking vector: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// After the MSI-X table entry has been updated, it is necessary to
|
// After the MSI-X table entry has been updated, it is necessary to
|
||||||
|
|||||||
688
pci/src/vfio.rs
688
pci/src/vfio.rs
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
use crate::vfio::{Interrupt, Vfio, VfioCommon, VfioError};
|
use crate::vfio::{Interrupt, UserMemoryRegion, Vfio, VfioCommon, VfioError};
|
||||||
use crate::{BarReprogrammingParams, PciBarRegionType, VfioPciError};
|
use crate::{BarReprogrammingParams, PciBarConfiguration, VfioPciError};
|
||||||
use crate::{
|
use crate::{
|
||||||
PciBdf, PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
PciBdf, PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
||||||
};
|
};
|
||||||
@@ -21,18 +21,17 @@ use vfio_user::{Client, Error as VfioUserError};
|
|||||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||||
use vm_device::interrupt::{InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig};
|
use vm_device::interrupt::{InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig};
|
||||||
use vm_device::BusDevice;
|
use vm_device::{BusDevice, Resource};
|
||||||
use vm_memory::bitmap::AtomicBitmap;
|
use vm_memory::bitmap::AtomicBitmap;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryRegion, GuestRegionMmap,
|
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryRegion, GuestRegionMmap,
|
||||||
GuestUsize,
|
|
||||||
};
|
};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct VfioUserPciDevice {
|
pub struct VfioUserPciDevice {
|
||||||
|
id: String,
|
||||||
vm: Arc<dyn hypervisor::Vm>,
|
vm: Arc<dyn hypervisor::Vm>,
|
||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
vfio_wrapper: VfioUserClientWrapper,
|
|
||||||
common: VfioCommon,
|
common: VfioCommon,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +62,10 @@ impl PciSubclass for PciVfioUserSubclass {
|
|||||||
|
|
||||||
impl VfioUserPciDevice {
|
impl VfioUserPciDevice {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String,
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
msi_interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
||||||
bdf: PciBdf,
|
bdf: PciBdf,
|
||||||
) -> Result<Self, VfioUserPciDeviceError> {
|
) -> Result<Self, VfioUserPciDeviceError> {
|
||||||
@@ -103,17 +103,20 @@ impl VfioUserPciDevice {
|
|||||||
msi: None,
|
msi: None,
|
||||||
msix: None,
|
msix: None,
|
||||||
},
|
},
|
||||||
|
msi_interrupt_manager,
|
||||||
|
legacy_interrupt_group,
|
||||||
|
vfio_wrapper: Arc::new(vfio_wrapper) as Arc<dyn Vfio>,
|
||||||
};
|
};
|
||||||
|
|
||||||
common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper, bdf);
|
common.parse_capabilities(bdf);
|
||||||
common
|
common
|
||||||
.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)
|
.initialize_legacy_interrupt()
|
||||||
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
id,
|
||||||
vm: vm.clone(),
|
vm: vm.clone(),
|
||||||
client,
|
client,
|
||||||
vfio_wrapper,
|
|
||||||
common,
|
common,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -143,6 +146,15 @@ impl VfioUserPciDevice {
|
|||||||
.file_offset
|
.file_offset
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
let sparse_areas = self
|
||||||
|
.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.region(mmio_region.index)
|
||||||
|
.unwrap()
|
||||||
|
.sparse_areas
|
||||||
|
.clone();
|
||||||
|
|
||||||
if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
|
if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
|
||||||
let mut prot = 0;
|
let mut prot = 0;
|
||||||
if region_flags & VFIO_REGION_INFO_FLAG_READ != 0 {
|
if region_flags & VFIO_REGION_INFO_FLAG_READ != 0 {
|
||||||
@@ -152,41 +164,57 @@ impl VfioUserPciDevice {
|
|||||||
prot |= libc::PROT_WRITE;
|
prot |= libc::PROT_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
let host_addr = unsafe {
|
let mmaps = if sparse_areas.is_empty() {
|
||||||
libc::mmap(
|
vec![vfio_region_sparse_mmap_area {
|
||||||
null_mut(),
|
offset: 0,
|
||||||
mmio_region.length as usize,
|
size: mmio_region.length,
|
||||||
prot,
|
}]
|
||||||
libc::MAP_SHARED,
|
} else {
|
||||||
file_offset.as_ref().unwrap().file().as_raw_fd(),
|
sparse_areas
|
||||||
file_offset.as_ref().unwrap().start() as libc::off_t,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if host_addr == libc::MAP_FAILED {
|
for s in mmaps.iter() {
|
||||||
error!(
|
let host_addr = unsafe {
|
||||||
"Could not mmap regions, error:{}",
|
libc::mmap(
|
||||||
std::io::Error::last_os_error()
|
null_mut(),
|
||||||
|
s.size as usize,
|
||||||
|
prot,
|
||||||
|
libc::MAP_SHARED,
|
||||||
|
file_offset.as_ref().unwrap().file().as_raw_fd(),
|
||||||
|
file_offset.as_ref().unwrap().start() as libc::off_t
|
||||||
|
+ s.offset as libc::off_t,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if host_addr == libc::MAP_FAILED {
|
||||||
|
error!(
|
||||||
|
"Could not mmap regions, error:{}",
|
||||||
|
std::io::Error::last_os_error()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_memory_region = UserMemoryRegion {
|
||||||
|
slot: mem_slot(),
|
||||||
|
start: mmio_region.start.0 + s.offset,
|
||||||
|
size: s.size,
|
||||||
|
host_addr: host_addr as u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
mmio_region.user_memory_regions.push(user_memory_region);
|
||||||
|
|
||||||
|
let mem_region = vm.make_user_memory_region(
|
||||||
|
user_memory_region.slot,
|
||||||
|
user_memory_region.start,
|
||||||
|
user_memory_region.size,
|
||||||
|
user_memory_region.host_addr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
continue;
|
|
||||||
|
vm.create_user_memory_region(mem_region)
|
||||||
|
.map_err(VfioUserPciDeviceError::MapRegionGuest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let slot = mem_slot();
|
|
||||||
let mem_region = vm.make_user_memory_region(
|
|
||||||
slot,
|
|
||||||
mmio_region.start.0,
|
|
||||||
mmio_region.length as u64,
|
|
||||||
host_addr as u64,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
vm.create_user_memory_region(mem_region)
|
|
||||||
.map_err(VfioUserPciDeviceError::MapRegionGuest)?;
|
|
||||||
|
|
||||||
mmio_region.mem_slot = Some(slot);
|
|
||||||
mmio_region.host_addr = Some(host_addr as u64);
|
|
||||||
mmio_region.mmap_size = Some(mmio_region.length as usize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,17 +223,13 @@ impl VfioUserPciDevice {
|
|||||||
|
|
||||||
pub fn unmap_mmio_regions(&mut self) {
|
pub fn unmap_mmio_regions(&mut self) {
|
||||||
for mmio_region in self.common.mmio_regions.iter() {
|
for mmio_region in self.common.mmio_regions.iter() {
|
||||||
if let (Some(host_addr), Some(mmap_size), Some(mem_slot)) = (
|
for user_memory_region in mmio_region.user_memory_regions.iter() {
|
||||||
mmio_region.host_addr,
|
|
||||||
mmio_region.mmap_size,
|
|
||||||
mmio_region.mem_slot,
|
|
||||||
) {
|
|
||||||
// Remove region
|
// Remove region
|
||||||
let r = self.vm.make_user_memory_region(
|
let r = self.vm.make_user_memory_region(
|
||||||
mem_slot,
|
user_memory_region.slot,
|
||||||
mmio_region.start.raw_value(),
|
user_memory_region.start,
|
||||||
mmap_size as u64,
|
user_memory_region.size,
|
||||||
host_addr as u64,
|
user_memory_region.host_addr,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
@@ -214,7 +238,13 @@ impl VfioUserPciDevice {
|
|||||||
error!("Could not remove the userspace memory region: {}", e);
|
error!("Could not remove the userspace memory region: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret = unsafe { libc::munmap(host_addr as *mut libc::c_void, mmap_size) };
|
// Remove mmaps
|
||||||
|
let ret = unsafe {
|
||||||
|
libc::munmap(
|
||||||
|
user_memory_region.host_addr as *mut libc::c_void,
|
||||||
|
user_memory_region.size as usize,
|
||||||
|
)
|
||||||
|
};
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
error!(
|
error!(
|
||||||
"Could not unmap region {}, error:{}",
|
"Could not unmap region {}, error:{}",
|
||||||
@@ -392,9 +422,10 @@ impl PciDevice for VfioUserPciDevice {
|
|||||||
&mut self,
|
&mut self,
|
||||||
allocator: &Arc<Mutex<SystemAllocator>>,
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
mmio_allocator: &mut AddressAllocator,
|
mmio_allocator: &mut AddressAllocator,
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
resources: Option<Vec<Resource>>,
|
||||||
|
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
|
||||||
self.common
|
self.common
|
||||||
.allocate_bars(allocator, mmio_allocator, &self.vfio_wrapper)
|
.allocate_bars(allocator, mmio_allocator, resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_bars(
|
fn free_bars(
|
||||||
@@ -425,22 +456,19 @@ impl PciDevice for VfioUserPciDevice {
|
|||||||
offset: u64,
|
offset: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Option<Arc<Barrier>> {
|
) -> Option<Arc<Barrier>> {
|
||||||
self.common
|
self.common.write_config_register(reg_idx, offset, data)
|
||||||
.write_config_register(reg_idx, offset, data, &self.vfio_wrapper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
|
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
|
||||||
self.common
|
self.common.read_config_register(reg_idx)
|
||||||
.read_config_register(reg_idx, &self.vfio_wrapper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_bar(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
fn read_bar(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
||||||
self.common.read_bar(base, offset, data, &self.vfio_wrapper)
|
self.common.read_bar(base, offset, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bar(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
fn write_bar(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
||||||
self.common
|
self.common.write_bar(base, offset, data)
|
||||||
.write_bar(base, offset, data, &self.vfio_wrapper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_bar(&mut self, old_base: u64, new_base: u64) -> Result<(), std::io::Error> {
|
fn move_bar(&mut self, old_base: u64, new_base: u64) -> Result<(), std::io::Error> {
|
||||||
@@ -449,35 +477,41 @@ impl PciDevice for VfioUserPciDevice {
|
|||||||
if mmio_region.start.raw_value() == old_base {
|
if mmio_region.start.raw_value() == old_base {
|
||||||
mmio_region.start = GuestAddress(new_base);
|
mmio_region.start = GuestAddress(new_base);
|
||||||
|
|
||||||
if let Some(mem_slot) = mmio_region.mem_slot {
|
for user_memory_region in mmio_region.user_memory_regions.iter_mut() {
|
||||||
if let Some(host_addr) = mmio_region.host_addr {
|
// Remove old region
|
||||||
// Remove original region
|
let old_region = self.vm.make_user_memory_region(
|
||||||
let old_region = self.vm.make_user_memory_region(
|
user_memory_region.slot,
|
||||||
mem_slot,
|
user_memory_region.start,
|
||||||
old_base,
|
user_memory_region.size,
|
||||||
mmio_region.length as u64,
|
user_memory_region.host_addr,
|
||||||
host_addr as u64,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
self.vm
|
||||||
.remove_user_memory_region(old_region)
|
.remove_user_memory_region(old_region)
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
|
|
||||||
let new_region = self.vm.make_user_memory_region(
|
// Update the user memory region with the correct start address.
|
||||||
mem_slot,
|
if new_base > old_base {
|
||||||
new_base,
|
user_memory_region.start += new_base - old_base;
|
||||||
mmio_region.length as u64,
|
} else {
|
||||||
host_addr as u64,
|
user_memory_region.start -= old_base - new_base;
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
|
||||||
.create_user_memory_region(new_region)
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert new region
|
||||||
|
let new_region = self.vm.make_user_memory_region(
|
||||||
|
user_memory_region.slot,
|
||||||
|
user_memory_region.start,
|
||||||
|
user_memory_region.size,
|
||||||
|
user_memory_region.host_addr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.vm
|
||||||
|
.create_user_memory_region(new_region)
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
}
|
}
|
||||||
info!("Moved bar 0x{:x} -> 0x{:x}", old_base, new_base);
|
info!("Moved bar 0x{:x} -> 0x{:x}", old_base, new_base);
|
||||||
}
|
}
|
||||||
@@ -485,6 +519,10 @@ impl PciDevice for VfioUserPciDevice {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VfioUserPciDevice {
|
impl Drop for VfioUserPciDevice {
|
||||||
@@ -493,18 +531,22 @@ impl Drop for VfioUserPciDevice {
|
|||||||
|
|
||||||
if let Some(msix) = &self.common.interrupt.msix {
|
if let Some(msix) = &self.common.interrupt.msix {
|
||||||
if msix.bar.enabled() {
|
if msix.bar.enabled() {
|
||||||
self.common.disable_msix(&self.vfio_wrapper);
|
self.common.disable_msix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(msi) = &self.common.interrupt.msi {
|
if let Some(msi) = &self.common.interrupt.msi {
|
||||||
if msi.cfg.enabled() {
|
if msi.cfg.enabled() {
|
||||||
self.common.disable_msi(&self.vfio_wrapper)
|
self.common.disable_msi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.common.interrupt.intx_in_use() {
|
if self.common.interrupt.intx_in_use() {
|
||||||
self.common.disable_intx(&self.vfio_wrapper);
|
self.common.disable_intx();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = self.client.lock().unwrap().shutdown() {
|
||||||
|
error!("Failed shutting down vfio-user client: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,17 @@
|
|||||||
name = "performance-metrics"
|
name = "performance-metrics"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "3.1.5", features = ["wrap_help","cargo"] }
|
clap = { version = "3.1.18", features = ["wrap_help","cargo"] }
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
serde = { version = "1.0.136", features = ["rc"] }
|
serde = { version = "1.0.137", features = ["rc", "derive"] }
|
||||||
serde_derive = "1.0.136"
|
serde_json = "1.0.81"
|
||||||
serde_json = "1.0.78"
|
|
||||||
test_infra = { path = "../test_infra" }
|
test_infra = { path = "../test_infra" }
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.31"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "3.1.5", features = ["wrap_help"] }
|
clap = { version = "3.1.18", features = ["cargo"] }
|
||||||
|
|||||||
@@ -12,8 +12,14 @@ mod performance_tests;
|
|||||||
|
|
||||||
use clap::{Arg, Command as ClapCommand};
|
use clap::{Arg, Command as ClapCommand};
|
||||||
use performance_tests::*;
|
use performance_tests::*;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{env, fmt, process::Command, sync::mpsc::channel, thread, time::Duration};
|
use std::{
|
||||||
|
env, fmt,
|
||||||
|
process::Command,
|
||||||
|
sync::{mpsc::channel, Arc},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@@ -22,10 +28,6 @@ enum Error {
|
|||||||
TestTimeout,
|
TestTimeout,
|
||||||
#[error("Error: test failed")]
|
#[error("Error: test failed")]
|
||||||
TestFailed,
|
TestFailed,
|
||||||
#[error("Error creating log file: {0}")]
|
|
||||||
ReportFileCreation(std::io::Error),
|
|
||||||
#[error("Error writing log file: {0}")]
|
|
||||||
ReportFileWrite(std::io::Error),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
@@ -88,6 +90,21 @@ impl Default for MetricsReport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct PerformanceTestOverrides {
|
||||||
|
test_iterations: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PerformanceTestOverrides {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if let Some(test_iterations) = self.test_iterations {
|
||||||
|
write!(f, "test_iterations = {}", test_iterations)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PerformanceTestControl {
|
pub struct PerformanceTestControl {
|
||||||
test_timeout: u32,
|
test_timeout: u32,
|
||||||
test_iterations: u32,
|
test_iterations: u32,
|
||||||
@@ -95,6 +112,7 @@ pub struct PerformanceTestControl {
|
|||||||
queue_size: Option<u32>,
|
queue_size: Option<u32>,
|
||||||
net_rx: Option<bool>,
|
net_rx: Option<bool>,
|
||||||
fio_ops: Option<FioOps>,
|
fio_ops: Option<FioOps>,
|
||||||
|
num_boot_vcpus: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PerformanceTestControl {
|
impl fmt::Display for PerformanceTestControl {
|
||||||
@@ -129,6 +147,7 @@ impl PerformanceTestControl {
|
|||||||
queue_size: None,
|
queue_size: None,
|
||||||
net_rx: None,
|
net_rx: None,
|
||||||
fio_ops: None,
|
fio_ops: None,
|
||||||
|
num_boot_vcpus: Some(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,19 +159,23 @@ struct PerformanceTest {
|
|||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
pub func_ptr: fn(&PerformanceTestControl) -> f64,
|
pub func_ptr: fn(&PerformanceTestControl) -> f64,
|
||||||
pub control: PerformanceTestControl,
|
pub control: PerformanceTestControl,
|
||||||
|
unit_adjuster: fn(f64) -> f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PerformanceTest {
|
impl PerformanceTest {
|
||||||
pub fn run(&self) -> PerformanceTestResult {
|
pub fn run(&self, overrides: &PerformanceTestOverrides) -> PerformanceTestResult {
|
||||||
let mut metrics = Vec::new();
|
let mut metrics = Vec::new();
|
||||||
for _ in 0..self.control.test_iterations {
|
for _ in 0..overrides
|
||||||
|
.test_iterations
|
||||||
|
.unwrap_or(self.control.test_iterations)
|
||||||
|
{
|
||||||
metrics.push((self.func_ptr)(&self.control));
|
metrics.push((self.func_ptr)(&self.control));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mean = mean(&metrics).unwrap();
|
let mean = (self.unit_adjuster)(mean(&metrics).unwrap());
|
||||||
let std_dev = std_deviation(&metrics).unwrap();
|
let std_dev = (self.unit_adjuster)(std_deviation(&metrics).unwrap());
|
||||||
let max = metrics.clone().into_iter().reduce(f64::max).unwrap();
|
let max = (self.unit_adjuster)(metrics.clone().into_iter().reduce(f64::max).unwrap());
|
||||||
let min = metrics.clone().into_iter().reduce(f64::min).unwrap();
|
let min = (self.unit_adjuster)(metrics.clone().into_iter().reduce(f64::min).unwrap());
|
||||||
|
|
||||||
PerformanceTestResult {
|
PerformanceTestResult {
|
||||||
name: self.name.to_string(),
|
name: self.name.to_string(),
|
||||||
@@ -165,8 +188,9 @@ impl PerformanceTest {
|
|||||||
|
|
||||||
// Calculate the timeout for each test
|
// Calculate the timeout for each test
|
||||||
// Note: To cover the setup/cleanup time, 20s is added for each iteration of the test
|
// Note: To cover the setup/cleanup time, 20s is added for each iteration of the test
|
||||||
pub fn calc_timeout(&self) -> u64 {
|
pub fn calc_timeout(&self, test_iterations: &Option<u32>) -> u64 {
|
||||||
((self.control.test_timeout + 20) * self.control.test_iterations) as u64
|
((self.control.test_timeout + 20) * test_iterations.unwrap_or(self.control.test_iterations))
|
||||||
|
as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,24 +224,67 @@ fn std_deviation(data: &[f64]) -> Option<f64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_LIST: [PerformanceTest; 15] = [
|
mod adjuster {
|
||||||
|
pub fn identity(v: f64) -> f64 {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn s_to_ms(v: f64) -> f64 {
|
||||||
|
v * 1000.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bps_to_gbps(v: f64) -> f64 {
|
||||||
|
v / (1_000_000_000_f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Bps_to_MiBps(v: f64) -> f64 {
|
||||||
|
v / (1 << 20) as f64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_LIST: [PerformanceTest; 17] = [
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "boot_time_s",
|
name: "boot_time_ms",
|
||||||
func_ptr: performance_boot_time,
|
func_ptr: performance_boot_time,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
test_timeout: 2,
|
test_timeout: 2,
|
||||||
test_iterations: 10,
|
test_iterations: 10,
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::s_to_ms,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "boot_time_pmem_s",
|
name: "boot_time_pmem_ms",
|
||||||
func_ptr: performance_boot_time_pmem,
|
func_ptr: performance_boot_time_pmem,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
test_timeout: 2,
|
test_timeout: 2,
|
||||||
test_iterations: 10,
|
test_iterations: 10,
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::s_to_ms,
|
||||||
|
},
|
||||||
|
PerformanceTest {
|
||||||
|
name: "boot_time_16_vcpus_ms",
|
||||||
|
func_ptr: performance_boot_time,
|
||||||
|
control: PerformanceTestControl {
|
||||||
|
test_timeout: 2,
|
||||||
|
test_iterations: 10,
|
||||||
|
num_boot_vcpus: Some(16),
|
||||||
|
..PerformanceTestControl::default()
|
||||||
|
},
|
||||||
|
unit_adjuster: adjuster::s_to_ms,
|
||||||
|
},
|
||||||
|
PerformanceTest {
|
||||||
|
name: "boot_time_16_vcpus_pmem_ms",
|
||||||
|
func_ptr: performance_boot_time_pmem,
|
||||||
|
control: PerformanceTestControl {
|
||||||
|
test_timeout: 2,
|
||||||
|
test_iterations: 10,
|
||||||
|
num_boot_vcpus: Some(16),
|
||||||
|
..PerformanceTestControl::default()
|
||||||
|
},
|
||||||
|
unit_adjuster: adjuster::s_to_ms,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "virtio_net_latency_us",
|
name: "virtio_net_latency_us",
|
||||||
@@ -227,9 +294,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
queue_size: Some(256),
|
queue_size: Some(256),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::identity,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "virtio_net_throughput_single_queue_rx_bps",
|
name: "virtio_net_throughput_single_queue_rx_gbps",
|
||||||
func_ptr: performance_net_throughput,
|
func_ptr: performance_net_throughput,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -237,9 +305,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
net_rx: Some(true),
|
net_rx: Some(true),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::bps_to_gbps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "virtio_net_throughput_single_queue_tx_bps",
|
name: "virtio_net_throughput_single_queue_tx_gbps",
|
||||||
func_ptr: performance_net_throughput,
|
func_ptr: performance_net_throughput,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -247,9 +316,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
net_rx: Some(false),
|
net_rx: Some(false),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::bps_to_gbps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "virtio_net_throughput_multi_queue_rx_bps",
|
name: "virtio_net_throughput_multi_queue_rx_gbps",
|
||||||
func_ptr: performance_net_throughput,
|
func_ptr: performance_net_throughput,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(4),
|
num_queues: Some(4),
|
||||||
@@ -257,9 +327,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
net_rx: Some(true),
|
net_rx: Some(true),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::bps_to_gbps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "virtio_net_throughput_multi_queue_tx_bps",
|
name: "virtio_net_throughput_multi_queue_tx_gbps",
|
||||||
func_ptr: performance_net_throughput,
|
func_ptr: performance_net_throughput,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(4),
|
num_queues: Some(4),
|
||||||
@@ -267,9 +338,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
net_rx: Some(false),
|
net_rx: Some(false),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::bps_to_gbps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_read_Bps",
|
name: "block_read_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(1),
|
num_queues: Some(1),
|
||||||
@@ -277,9 +349,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::Read),
|
fio_ops: Some(FioOps::Read),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_write_Bps",
|
name: "block_write_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(1),
|
num_queues: Some(1),
|
||||||
@@ -287,9 +360,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::Write),
|
fio_ops: Some(FioOps::Write),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_random_read_Bps",
|
name: "block_random_read_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(1),
|
num_queues: Some(1),
|
||||||
@@ -297,9 +371,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::RandomRead),
|
fio_ops: Some(FioOps::RandomRead),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_random_write_Bps",
|
name: "block_random_write_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(1),
|
num_queues: Some(1),
|
||||||
@@ -307,9 +382,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::RandomWrite),
|
fio_ops: Some(FioOps::RandomWrite),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_multi_queue_read_Bps",
|
name: "block_multi_queue_read_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -317,9 +393,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::Read),
|
fio_ops: Some(FioOps::Read),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_multi_queue_write_Bps",
|
name: "block_multi_queue_write_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -327,9 +404,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::Write),
|
fio_ops: Some(FioOps::Write),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_multi_queue_random_read_Bps",
|
name: "block_multi_queue_random_read_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -337,9 +415,10 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::RandomRead),
|
fio_ops: Some(FioOps::RandomRead),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
PerformanceTest {
|
PerformanceTest {
|
||||||
name: "block_multi_queue_random_write_Bps",
|
name: "block_multi_queue_random_write_MiBps",
|
||||||
func_ptr: performance_block_io,
|
func_ptr: performance_block_io,
|
||||||
control: PerformanceTestControl {
|
control: PerformanceTestControl {
|
||||||
num_queues: Some(2),
|
num_queues: Some(2),
|
||||||
@@ -347,15 +426,24 @@ const TEST_LIST: [PerformanceTest; 15] = [
|
|||||||
fio_ops: Some(FioOps::RandomWrite),
|
fio_ops: Some(FioOps::RandomWrite),
|
||||||
..PerformanceTestControl::default()
|
..PerformanceTestControl::default()
|
||||||
},
|
},
|
||||||
|
unit_adjuster: adjuster::Bps_to_MiBps,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
fn run_test_with_timetout(test: &'static PerformanceTest) -> Result<PerformanceTestResult, Error> {
|
fn run_test_with_timeout(
|
||||||
|
test: &'static PerformanceTest,
|
||||||
|
overrides: &Arc<PerformanceTestOverrides>,
|
||||||
|
) -> Result<PerformanceTestResult, Error> {
|
||||||
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
|
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
|
||||||
|
let test_iterations = overrides.test_iterations;
|
||||||
|
let overrides = overrides.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
println!("Test '{}' running .. ({})", test.name, test.control);
|
println!(
|
||||||
|
"Test '{}' running .. (control: {}, overrides: {})",
|
||||||
|
test.name, test.control, overrides
|
||||||
|
);
|
||||||
|
|
||||||
let output = match std::panic::catch_unwind(|| test.run()) {
|
let output = match std::panic::catch_unwind(|| test.run(&overrides)) {
|
||||||
Ok(test_result) => {
|
Ok(test_result) => {
|
||||||
println!(
|
println!(
|
||||||
"Test '{}' .. ok: mean = {}, std_dev = {}",
|
"Test '{}' .. ok: mean = {}, std_dev = {}",
|
||||||
@@ -370,7 +458,7 @@ fn run_test_with_timetout(test: &'static PerformanceTest) -> Result<PerformanceT
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Todo: Need to cleanup/kill all hanging child processes
|
// Todo: Need to cleanup/kill all hanging child processes
|
||||||
let test_timeout = test.calc_timeout();
|
let test_timeout = test.calc_timeout(&test_iterations);
|
||||||
receiver
|
receiver
|
||||||
.recv_timeout(Duration::from_secs(test_timeout))
|
.recv_timeout(Duration::from_secs(test_timeout))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@@ -414,11 +502,24 @@ fn main() {
|
|||||||
.help("Report file. Standard error is used if not specified")
|
.help("Report file. Standard error is used if not specified")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("iterations")
|
||||||
|
.long("iterations")
|
||||||
|
.help("Override number of test iterations")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
|
// It seems that the tool (ethr) used for testing the virtio-net latency
|
||||||
|
// is not stable on AArch64, and therefore the latency test is currently
|
||||||
|
// skipped on AArch64.
|
||||||
|
let test_list: Vec<&PerformanceTest> = TEST_LIST
|
||||||
|
.iter()
|
||||||
|
.filter(|t| !(cfg!(target_arch = "aarch64") && t.name == "virtio_net_latency_us"))
|
||||||
|
.collect();
|
||||||
|
|
||||||
if cmd_arguments.is_present("list-tests") {
|
if cmd_arguments.is_present("list-tests") {
|
||||||
println!("List of available metrics tests:\n");
|
for test in test_list.iter() {
|
||||||
for test in TEST_LIST.iter() {
|
|
||||||
println!("\"{}\" ({})", test.name, test.control);
|
println!("\"{}\" ({})", test.name, test.control);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,31 +531,28 @@ fn main() {
|
|||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut report_file: Box<dyn std::io::Write + Send> =
|
|
||||||
if let Some(file) = cmd_arguments.value_of("report-file") {
|
|
||||||
Box::new(
|
|
||||||
std::fs::File::create(std::path::Path::new(file))
|
|
||||||
.map_err(Error::ReportFileCreation)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Box::new(std::io::stderr())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run performance tests sequentially and report results (in both readable/json format)
|
// Run performance tests sequentially and report results (in both readable/json format)
|
||||||
let mut metrics_report: MetricsReport = Default::default();
|
let mut metrics_report: MetricsReport = Default::default();
|
||||||
|
|
||||||
init_tests();
|
init_tests();
|
||||||
|
|
||||||
for test in TEST_LIST.iter() {
|
let overrides = Arc::new(PerformanceTestOverrides {
|
||||||
|
test_iterations: cmd_arguments
|
||||||
|
.value_of("iterations")
|
||||||
|
.map(|s| s.parse())
|
||||||
|
.transpose()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
for test in test_list.iter() {
|
||||||
if test_filter.is_empty() || test_filter.iter().any(|&s| test.name.contains(s)) {
|
if test_filter.is_empty() || test_filter.iter().any(|&s| test.name.contains(s)) {
|
||||||
match run_test_with_timetout(test) {
|
match run_test_with_timeout(test, &overrides) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
metrics_report.results.push(r);
|
metrics_report.results.push(r);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Aborting test due to error: '{:?}'", e);
|
eprintln!("Aborting test due to error: '{:?}'", e);
|
||||||
break;
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -462,13 +560,29 @@ fn main() {
|
|||||||
|
|
||||||
cleanup_tests();
|
cleanup_tests();
|
||||||
|
|
||||||
// Todo: Report/upload to the metrics database
|
let mut report_file: Box<dyn std::io::Write + Send> =
|
||||||
|
if let Some(file) = cmd_arguments.value_of("report-file") {
|
||||||
|
Box::new(
|
||||||
|
std::fs::File::create(std::path::Path::new(file))
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Error opening report file: {}: {}", file, e);
|
||||||
|
std::process::exit(1);
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Box::new(std::io::stdout())
|
||||||
|
};
|
||||||
|
|
||||||
report_file
|
report_file
|
||||||
.write(
|
.write_all(
|
||||||
serde_json::to_string_pretty(&metrics_report)
|
serde_json::to_string_pretty(&metrics_report)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
)
|
)
|
||||||
.map_err(Error::ReportFileWrite)
|
.map_err(|e| {
|
||||||
|
eprintln!("Error writing report file: {}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ use test_infra::Error as InfraError;
|
|||||||
use test_infra::*;
|
use test_infra::*;
|
||||||
use wait_timeout::ChildExt;
|
use wait_timeout::ChildExt;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-amd64-custom-20210609-0.raw";
|
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-amd64-custom-20210609-0.raw";
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-0-update-tool.raw";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum WaitTimeoutError {
|
enum WaitTimeoutError {
|
||||||
@@ -235,6 +238,7 @@ pub fn performance_net_throughput(control: &PerformanceTestControl) -> f64 {
|
|||||||
.default_disks()
|
.default_disks()
|
||||||
.args(&["--net", net_params.as_str()])
|
.args(&["--net", net_params.as_str()])
|
||||||
.capture_output()
|
.capture_output()
|
||||||
|
.verbosity(VerbosityLevel::Warn)
|
||||||
.set_print_cmd(false)
|
.set_print_cmd(false)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -364,6 +368,7 @@ pub fn performance_net_latency(control: &PerformanceTestControl) -> f64 {
|
|||||||
.default_disks()
|
.default_disks()
|
||||||
.args(&["--net", net_params.as_str()])
|
.args(&["--net", net_params.as_str()])
|
||||||
.capture_output()
|
.capture_output()
|
||||||
|
.verbosity(VerbosityLevel::Warn)
|
||||||
.set_print_cmd(false)
|
.set_print_cmd(false)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -469,7 +474,12 @@ fn parse_boot_time_output(output: &[u8]) -> Result<f64, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn measure_boot_time(cmd: &mut GuestCommand, test_timeout: u32) -> Result<f64, Error> {
|
fn measure_boot_time(cmd: &mut GuestCommand, test_timeout: u32) -> Result<f64, Error> {
|
||||||
let mut child = cmd.capture_output().set_print_cmd(false).spawn().unwrap();
|
let mut child = cmd
|
||||||
|
.capture_output()
|
||||||
|
.verbosity(VerbosityLevel::Warn)
|
||||||
|
.set_print_cmd(false)
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
thread::sleep(Duration::new(test_timeout as u64, 0));
|
thread::sleep(Duration::new(test_timeout as u64, 0));
|
||||||
let _ = child.kill();
|
let _ = child.kill();
|
||||||
@@ -496,6 +506,10 @@ pub fn performance_boot_time(control: &PerformanceTestControl) -> f64 {
|
|||||||
let mut cmd = GuestCommand::new(&guest);
|
let mut cmd = GuestCommand::new(&guest);
|
||||||
|
|
||||||
let c = cmd
|
let c = cmd
|
||||||
|
.args(&[
|
||||||
|
"--cpus",
|
||||||
|
&format!("boot={}", control.num_boot_vcpus.unwrap_or(1)),
|
||||||
|
])
|
||||||
.args(&["--memory", "size=1G"])
|
.args(&["--memory", "size=1G"])
|
||||||
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
||||||
.args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
.args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||||
@@ -519,6 +533,10 @@ pub fn performance_boot_time_pmem(control: &PerformanceTestControl) -> f64 {
|
|||||||
let guest = performance_test_new_guest(Box::new(focal));
|
let guest = performance_test_new_guest(Box::new(focal));
|
||||||
let mut cmd = GuestCommand::new(&guest);
|
let mut cmd = GuestCommand::new(&guest);
|
||||||
let c = cmd
|
let c = cmd
|
||||||
|
.args(&[
|
||||||
|
"--cpus",
|
||||||
|
&format!("boot={}", control.num_boot_vcpus.unwrap_or(1)),
|
||||||
|
])
|
||||||
.args(&["--memory", "size=1G,hugepages=on"])
|
.args(&["--memory", "size=1G,hugepages=on"])
|
||||||
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
||||||
.args(&["--cmdline", "root=/dev/pmem0p1 console=ttyS0 quiet rw"])
|
.args(&["--cmdline", "root=/dev/pmem0p1 console=ttyS0 quiet rw"])
|
||||||
@@ -618,7 +636,6 @@ fn parse_fio_output(output: &str, fio_ops: &FioOps, num_jobs: u32) -> Result<f64
|
|||||||
pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
|
pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
|
||||||
let test_timeout = control.test_timeout;
|
let test_timeout = control.test_timeout;
|
||||||
let num_queues = control.num_queues.unwrap();
|
let num_queues = control.num_queues.unwrap();
|
||||||
let queue_size = control.queue_size.unwrap();
|
|
||||||
let fio_ops = control.fio_ops.as_ref().unwrap();
|
let fio_ops = control.fio_ops.as_ref().unwrap();
|
||||||
|
|
||||||
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
||||||
@@ -636,10 +653,24 @@ pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
|
|||||||
.args(&["--memory", "size=4G"])
|
.args(&["--memory", "size=4G"])
|
||||||
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
.args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
||||||
.args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
.args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||||
.default_disks()
|
.args(&[
|
||||||
|
"--disk",
|
||||||
|
format!(
|
||||||
|
"path={}",
|
||||||
|
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
format!(
|
||||||
|
"path={}",
|
||||||
|
guest.disk_config.disk(DiskType::CloudInit).unwrap()
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
format!("path={}", BLK_IO_TEST_IMG).as_str(),
|
||||||
|
])
|
||||||
.default_net()
|
.default_net()
|
||||||
.args(&["--api-socket", &api_socket])
|
.args(&["--api-socket", &api_socket])
|
||||||
.capture_output()
|
.capture_output()
|
||||||
|
.verbosity(VerbosityLevel::Warn)
|
||||||
.set_print_cmd(false)
|
.set_print_cmd(false)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -647,25 +678,6 @@ pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
|
|||||||
let r = std::panic::catch_unwind(|| {
|
let r = std::panic::catch_unwind(|| {
|
||||||
guest.wait_vm_boot(None).unwrap();
|
guest.wait_vm_boot(None).unwrap();
|
||||||
|
|
||||||
// Hotplug test disk
|
|
||||||
assert!(Command::new(clh_command("ch-remote"))
|
|
||||||
.args(&[&format!("--api-socket={}", api_socket)])
|
|
||||||
.args(&[
|
|
||||||
"add-disk",
|
|
||||||
&format!(
|
|
||||||
"path={},num_queues={},queue_size={},direct=on",
|
|
||||||
BLK_IO_TEST_IMG, num_queues, queue_size
|
|
||||||
)
|
|
||||||
])
|
|
||||||
.stderr(Stdio::piped())
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.unwrap()
|
|
||||||
.wait_timeout(Duration::from_secs(5))
|
|
||||||
.unwrap()
|
|
||||||
.expect("Failed to hotplug test disk image")
|
|
||||||
.success());
|
|
||||||
|
|
||||||
let fio_command = format!(
|
let fio_command = format!(
|
||||||
"sudo fio --filename=/dev/vdc --name=test --output-format=json \
|
"sudo fio --filename=/dev/vdc --name=test --output-format=json \
|
||||||
--direct=1 --bs=4k --ioengine=io_uring --iodepth=64 \
|
--direct=1 --bs=4k --ioengine=io_uring --iodepth=64 \
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "qcow"
|
name = "qcow"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["The Chromium OS Authors"]
|
authors = ["The Chromium OS Authors"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
license = "BSD-3-Clause"
|
license = "BSD-3-Clause"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
@@ -10,7 +10,7 @@ path = "src/qcow.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
remain = "0.2.2"
|
remain = "0.2.3"
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
@@ -516,6 +516,19 @@ impl QcowFile {
|
|||||||
|
|
||||||
let l2_entries = cluster_size / size_of::<u64>() as u64;
|
let l2_entries = cluster_size / size_of::<u64>() as u64;
|
||||||
|
|
||||||
|
// Check for compressed blocks
|
||||||
|
for l2_addr_disk in l1_table.get_values() {
|
||||||
|
if *l2_addr_disk != 0 {
|
||||||
|
if let Err(e) = Self::read_l2_cluster(&mut raw_file, *l2_addr_disk) {
|
||||||
|
if let Some(os_error) = e.raw_os_error() {
|
||||||
|
if os_error == ENOTSUP {
|
||||||
|
return Err(Error::CompressedBlocksNotSupported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut qcow = QcowFile {
|
let mut qcow = QcowFile {
|
||||||
raw_file,
|
raw_file,
|
||||||
header,
|
header,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rate_limiter"
|
name = "rate_limiter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.119"
|
libc = "0.2.126"
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
253
release-notes.md
253
release-notes.md
@@ -1,3 +1,23 @@
|
|||||||
|
- [v24.0](#v240)
|
||||||
|
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
||||||
|
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
||||||
|
- [Sparse Mmap support](#sparse-mmap-support)
|
||||||
|
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||||
|
- [Notable Improvements](#notable-improvements)
|
||||||
|
- [Deprecations](#deprecations)
|
||||||
|
- [New on the Website](#new-on-the-website)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [v23.1](#v231)
|
||||||
|
- [v23.0](#v230)
|
||||||
|
- [vDPA Support](#vdpa-support)
|
||||||
|
- [Updated OS Support list](#updated-os-support-list)
|
||||||
|
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
||||||
|
- [`AMX` Support](#amx-support)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||||
|
- [Deprecations](#deprecations-1)
|
||||||
|
- [Contributors](#contributors-1)
|
||||||
|
- [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)
|
||||||
- [`virtio-iommu` Backed Segments](#virtio-iommu-backed-segments)
|
- [`virtio-iommu` Backed Segments](#virtio-iommu-backed-segments)
|
||||||
@@ -5,15 +25,15 @@
|
|||||||
- [`virtio-balloon` Free Page Reporting](#virtio-balloon-free-page-reporting)
|
- [`virtio-balloon` Free Page Reporting](#virtio-balloon-free-page-reporting)
|
||||||
- [Support for Direct Kernel Booting with TDX](#support-for-direct-kernel-booting-with-tdx)
|
- [Support for Direct Kernel Booting with TDX](#support-for-direct-kernel-booting-with-tdx)
|
||||||
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
||||||
- [Documentation Under CC-BY-4.0 Licese](#documentation-under-cc-by-40-licese)
|
- [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)
|
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors-2)
|
||||||
- [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-1)
|
- [Notable Bug fixes](#notable-bug-fixes-3)
|
||||||
- [Contributors](#contributors-1)
|
- [Contributors](#contributors-3)
|
||||||
- [v20.2](#v202)
|
- [v20.2](#v202)
|
||||||
- [v20.1](#v201)
|
- [v20.1](#v201)
|
||||||
- [v20.0](#v200)
|
- [v20.0](#v200)
|
||||||
@@ -22,8 +42,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-2)
|
- [Notable bug fixes](#notable-bug-fixes-4)
|
||||||
- [Contributors](#contributors-2)
|
- [Contributors](#contributors-4)
|
||||||
- [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)
|
||||||
@@ -31,8 +51,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-3)
|
- [Notable bug fixes](#notable-bug-fixes-5)
|
||||||
- [Contributors](#contributors-3)
|
- [Contributors](#contributors-5)
|
||||||
- [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)
|
||||||
@@ -42,31 +62,31 @@
|
|||||||
- [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-4)
|
- [Notable bug fixes](#notable-bug-fixes-6)
|
||||||
- [Contributors](#contributors-4)
|
- [Contributors](#contributors-6)
|
||||||
- [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-5)
|
- [Notable bug fixes](#notable-bug-fixes-7)
|
||||||
- [Contributors](#contributors-5)
|
- [Contributors](#contributors-7)
|
||||||
- [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-6)
|
- [Notable bug fixes](#notable-bug-fixes-8)
|
||||||
- [Removed functionality](#removed-functionality)
|
- [Removed functionality](#removed-functionality)
|
||||||
- [Contributors](#contributors-6)
|
- [Contributors](#contributors-8)
|
||||||
- [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)
|
||||||
- [Support for runtime control of `virtio-net` guest offload](#support-for-runtime-control-of-virtio-net-guest-offload)
|
- [Support for runtime control of `virtio-net` guest offload](#support-for-runtime-control-of-virtio-net-guest-offload)
|
||||||
- [`--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)
|
- [Deprecations](#deprecations-2)
|
||||||
- [Contributors](#contributors-7)
|
- [Contributors](#contributors-9)
|
||||||
- [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)
|
||||||
@@ -75,8 +95,8 @@
|
|||||||
- [Updated hotplug documentation](#updated-hotplug-documentation)
|
- [Updated hotplug documentation](#updated-hotplug-documentation)
|
||||||
- [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-1)
|
- [Deprecations](#deprecations-3)
|
||||||
- [Contributors](#contributors-8)
|
- [Contributors](#contributors-10)
|
||||||
- [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)
|
||||||
@@ -84,13 +104,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-9)
|
- [Contributors](#contributors-11)
|
||||||
- [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-10)
|
- [Contributors](#contributors-12)
|
||||||
- [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)
|
||||||
@@ -102,15 +122,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-7)
|
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||||
- [Contributors](#contributors-11)
|
- [Contributors](#contributors-13)
|
||||||
- [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-8)
|
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||||
- [Contributors](#contributors-12)
|
- [Contributors](#contributors-14)
|
||||||
- [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)
|
||||||
@@ -123,17 +143,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-9)
|
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||||
- [Contributors](#contributors-13)
|
- [Contributors](#contributors-15)
|
||||||
- [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-10)
|
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||||
- [Contributors](#contributors-14)
|
- [Contributors](#contributors-16)
|
||||||
- [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)
|
||||||
@@ -143,14 +163,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-15)
|
- [Contributors](#contributors-17)
|
||||||
- [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-16)
|
- [Contributors](#contributors-18)
|
||||||
- [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)
|
||||||
@@ -158,7 +178,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-17)
|
- [Contributors](#contributors-19)
|
||||||
- [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)
|
||||||
@@ -167,7 +187,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-18)
|
- [Contributors](#contributors-20)
|
||||||
- [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)
|
||||||
@@ -194,10 +214,169 @@
|
|||||||
- [Unit testing](#unit-testing)
|
- [Unit testing](#unit-testing)
|
||||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||||
|
|
||||||
|
# v24.0
|
||||||
|
|
||||||
|
This release has been tracked through the [v24.0
|
||||||
|
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/28).
|
||||||
|
|
||||||
|
### Bypass Mode for `virtio-iommu`
|
||||||
|
|
||||||
|
`virtio-iommu` specification describes how a device can be attached by default
|
||||||
|
to a bypass domain. This feature is particularly helpful for booting a VM with
|
||||||
|
guest software which doesn't support `virtio-iommu` but still need to access
|
||||||
|
the device. Now that Cloud Hypervisor supports this feature, it can boot a VM
|
||||||
|
with Rust Hypervisor Firmware or OVMF even if the `virtio-block` device exposing
|
||||||
|
the disk image is placed behind a virtual IOMMU.
|
||||||
|
|
||||||
|
### Ensure Identifiers Uniqueness
|
||||||
|
|
||||||
|
Multiple checks have been added to the code to prevent devices with identical
|
||||||
|
identifiers from being created, and therefore avoid unexpected behaviors at boot
|
||||||
|
or whenever a device was hot plugged into the VM.
|
||||||
|
|
||||||
|
### Sparse Mmap support
|
||||||
|
|
||||||
|
Sparse mmap support has been added to both VFIO and vfio-user devices. This
|
||||||
|
allows the device regions that are not fully mappable to be partially mapped.
|
||||||
|
And the more a device region can be mapped into the guest address space, the
|
||||||
|
fewer VM exits will be generated when this device is accessed. This directly
|
||||||
|
impacts the performance related to this device.
|
||||||
|
|
||||||
|
### Expose Platform Serial Number
|
||||||
|
|
||||||
|
A new `serial_number` option has been added to `--platform`, allowing a user to
|
||||||
|
set a specific serial number for the platform. This number is exposed to the
|
||||||
|
guest through the SMBIOS.
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Fix loading RAW firmware (#4072)
|
||||||
|
* Reject compressed QCOW images (#4055)
|
||||||
|
* Reject virtio-mem resize if device is not activated (#4003)
|
||||||
|
* Fix potential mmap leaks from VFIO/vfio-user MMIO regions (#4069)
|
||||||
|
* Fix algorithm finding HOB memory resources (#3983)
|
||||||
|
|
||||||
|
### Notable Improvements
|
||||||
|
|
||||||
|
* Refactor interrupt handling (#4083)
|
||||||
|
* Load kernel asynchronously (#4022)
|
||||||
|
* Only create ACPI memory manager DSDT when resizable (#4013)
|
||||||
|
|
||||||
|
### Deprecations
|
||||||
|
|
||||||
|
Deprecated features will be removed in a subsequent release and users should
|
||||||
|
plan to use alternatives
|
||||||
|
|
||||||
|
* The `mergeable` option from the `virtio-pmem` support has been deprecated
|
||||||
|
(#3968)
|
||||||
|
* The `dax` option from the `virtio-fs` support has been deprecated (#3889)
|
||||||
|
|
||||||
|
### New on the Website
|
||||||
|
|
||||||
|
A new blog post [Achieving Bare Metal Performance Within a Virtual
|
||||||
|
Machine](https://www.cloudhypervisor.org/blog/achieving-bare-metal-performance-within-a-virtual-machine)
|
||||||
|
has been added to the Cloud Hypervisor website.
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Fabiano Fidêncio <fabiano.fidencio@intel.com>
|
||||||
|
* LiHui <andrewli@kubesphere.io>
|
||||||
|
* Maksym Pavlenko <pavlenko.maksym@gmail.com>
|
||||||
|
* Rob Bradford <robert.bradford@intel.com>
|
||||||
|
* Sebastien Boeuf <sebastien.boeuf@intel.com>
|
||||||
|
* Steven Dake <steven.dake@gmail.com>
|
||||||
|
* Vincent Batts <vbatts@hashbangbash.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
|
||||||
|
# v23.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Add some missing seccomp rules
|
||||||
|
* Remove `virtio-fs` filesystem entries from config on removal
|
||||||
|
* Do not delete API socket on API server start (#4026)
|
||||||
|
* Reject `virtio-mem` resize if the guest doesn't activate the device
|
||||||
|
* Fix OpenAPI naming of I/O throttling knobs
|
||||||
|
|
||||||
|
# v23.0
|
||||||
|
|
||||||
|
This release has been tracked through the [v23.0
|
||||||
|
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/27).
|
||||||
|
|
||||||
|
### vDPA Support
|
||||||
|
|
||||||
|
A vDPA device has a datapath that complies with the virtio specification but
|
||||||
|
with a vendor specific control path. The addition of `--vdpa` and the REST API
|
||||||
|
equivalent allows the use of these devices with Cloud Hypervisor.
|
||||||
|
|
||||||
|
### Updated OS Support list
|
||||||
|
|
||||||
|
The list of officially supported and tested OS versions has been updated to
|
||||||
|
include Ubuntu "jammy" 22.04 and EOLed versions removed.
|
||||||
|
|
||||||
|
### `AArch64` Memory Map Improvements
|
||||||
|
|
||||||
|
The memory map when running on `AArch64` has been improved for the handling of
|
||||||
|
the UEFI region which means that the booted guest OS now has full access to its
|
||||||
|
allocated RAM. (#3938)
|
||||||
|
|
||||||
|
### `AMX` Support
|
||||||
|
|
||||||
|
Under a compile time gate of `amx` it is possible compile in support for the
|
||||||
|
`AMX` instruction set extension for guest use. This also requires runtime
|
||||||
|
enabling with `--cpu features=amx`.
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Generate error when incorrect HTTP method used for some API endpoints (#3887)
|
||||||
|
* CMOS based reset is now available to support rebooting on "jammy" (#3914)
|
||||||
|
* ACPI tables are not produced for memory hotplug when running with
|
||||||
|
`virtio-mem` (#3883)
|
||||||
|
* `virtio-iommu` backed PCI segments are now comprehensively placed behind the
|
||||||
|
vIOMMU (#3870)
|
||||||
|
* Seccomp rules have been extended for `virtio-fs` to support direct access
|
||||||
|
(#3848)
|
||||||
|
|
||||||
|
### Deprecations
|
||||||
|
|
||||||
|
Deprecated features will be removed in a subsequent release and users should
|
||||||
|
plan to use alternatives
|
||||||
|
|
||||||
|
* The `mergeable` option from the `virtio-pmem` support has been deprecated
|
||||||
|
(#3968)
|
||||||
|
* The `dax` option from the `virtio-fs` support has been deprecated (#3889)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Fabiano Fidêncio <fabiano.fidencio@intel.com>
|
||||||
|
* Henry Wang <Henry.Wang@arm.com>
|
||||||
|
* Jianyong Wu <jianyong.wu@arm.com>
|
||||||
|
* LiHui <andrewli@kubesphere.io>
|
||||||
|
* Michael Zhao <michael.zhao@arm.com>
|
||||||
|
* Rob Bradford <robert.bradford@intel.com>
|
||||||
|
* Sebastien Boeuf <sebastien.boeuf@intel.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
* William Douglas <william.douglas@intel.com>
|
||||||
|
* Yi Wang <wang.yi59@zte.com.cn>
|
||||||
|
|
||||||
|
# v22.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* VFIO ioctl reordering to fix MSI on AMD platforms (#3827)
|
||||||
|
* Fix `virtio-net` control queue (#3829)
|
||||||
|
|
||||||
# v22.0
|
# v22.0
|
||||||
|
|
||||||
This release has been tracked through the [v21.0
|
This release has been tracked through the [v22.0
|
||||||
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/24).
|
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/25).
|
||||||
|
|
||||||
### GDB Debug Stub Support
|
### GDB Debug Stub Support
|
||||||
|
|
||||||
@@ -206,7 +385,6 @@ by the `gdb` compile time feature and details of how to use it can be found in
|
|||||||
the [gdb
|
the [gdb
|
||||||
documentation](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/gdb.md).
|
documentation](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/gdb.md).
|
||||||
|
|
||||||
|
|
||||||
### `virtio-iommu` Backed Segments
|
### `virtio-iommu` Backed Segments
|
||||||
|
|
||||||
In order to facilitate hotplug devices that require being behind an IOMMU (e.g.
|
In order to facilitate hotplug devices that require being behind an IOMMU (e.g.
|
||||||
@@ -218,7 +396,6 @@ will place all the specified segments behind the IOMMU.
|
|||||||
It is now possible to change the VM configuration (e.g. add or remove devices,
|
It is now possible to change the VM configuration (e.g. add or remove devices,
|
||||||
resize) before the VM is booted.
|
resize) before the VM is booted.
|
||||||
|
|
||||||
|
|
||||||
### `virtio-balloon` Free Page Reporting
|
### `virtio-balloon` Free Page Reporting
|
||||||
|
|
||||||
If `--balloon free_page_reporting=on` is used then the guest can report pages
|
If `--balloon free_page_reporting=on` is used then the guest can report pages
|
||||||
@@ -238,7 +415,7 @@ has been updated for this usage.
|
|||||||
A PMU is now available on AArch64 for guest performance profiling. This will be
|
A PMU is now available on AArch64 for guest performance profiling. This will be
|
||||||
exposed automatically if available from the host.
|
exposed automatically if available from the host.
|
||||||
|
|
||||||
### Documentation Under CC-BY-4.0 Licese
|
### Documentation Under CC-BY-4.0 License
|
||||||
|
|
||||||
The documentation is now licensed under the "Creative Commons Attribution 4.0
|
The documentation is now licensed under the "Creative Commons Attribution 4.0
|
||||||
International" license which is aligned with the project charter under the
|
International" license which is aligned with the project charter under the
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
FROM ubuntu:20.04 as dev
|
FROM ubuntu:20.04 as dev
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG RUST_TOOLCHAIN="1.59.0"
|
ARG RUST_TOOLCHAIN="1.60.0"
|
||||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||||
@@ -112,7 +112,7 @@ 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 59f3cdacb13bd2a19c4a86be04792b0ee4491172 \
|
&& git checkout 6301f8915de32baed10dba1eebed556a6749211a \
|
||||||
&& git submodule update --init \
|
&& git submodule update --init \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& ./scripts/pkgdep.sh \
|
&& ./scripts/pkgdep.sh \
|
||||||
|
|||||||
@@ -1,25 +1,32 @@
|
|||||||
# This spec file assumes you're building on an environment where:
|
# If this flag is set to 1, rustup installation needs to exist on the system and
|
||||||
# * You have access to the internet during the build
|
# <arch>-unknown-linux-gnu target is required.
|
||||||
# * You have rustup installed on your system
|
# If this flag is set to 0, distro specific Rust packages will be pulled into the build environment.
|
||||||
# * You have both x86_64-unknown-linux-gnu and x86_64-unknown-linux-musl
|
|
||||||
# targets installed.
|
|
||||||
|
|
||||||
%define using_rustup 1
|
%define using_rustup 1
|
||||||
|
# If this flag is set to 1, <arch>-unknown-linux-musl target is required.
|
||||||
%define using_musl_libc 1
|
%define using_musl_libc 1
|
||||||
|
# If this flag is set to 1, the vendored crates archive and cargo.toml need to be prepared and
|
||||||
|
# offline build is implied. Attached script update_src can be used for the vendorization.
|
||||||
|
# If this flag is set to 0, access to the internet is required during the build.
|
||||||
|
%define using_vendored_crates 0
|
||||||
|
|
||||||
Name: cloud-hypervisor
|
Name: cloud-hypervisor
|
||||||
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
||||||
Version: 22.0
|
Version: 24.0
|
||||||
Release: 0%{?dist}
|
Release: 0%{?dist}
|
||||||
License: ASL 2.0 or BSD-3-clause
|
License: ASL 2.0 or BSD-3-clause
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
Source0: https://github.com/cloud-hypervisor/cloud-hypervisor/archive/v%{version}.tar.gz
|
Source0: https://github.com/cloud-hypervisor/cloud-hypervisor/archive/v%{version}.tar.gz
|
||||||
ExclusiveArch: x86_64
|
%if 0%{?using_vendored_crates}
|
||||||
|
Source1: vendor.tar.gz
|
||||||
|
Source2: config.toml
|
||||||
|
%endif
|
||||||
|
ExclusiveArch: x86_64 aarch64
|
||||||
|
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
BuildRequires: glibc-devel
|
BuildRequires: glibc-devel
|
||||||
BuildRequires: binutils
|
BuildRequires: binutils
|
||||||
BuildRequires: git
|
BuildRequires: git
|
||||||
|
BuildRequires: openssl-devel
|
||||||
|
|
||||||
%if ! 0%{?using_rustup}
|
%if ! 0%{?using_rustup}
|
||||||
BuildRequires: rust
|
BuildRequires: rust
|
||||||
@@ -31,29 +38,51 @@ Requires: glibc
|
|||||||
Requires: libgcc
|
Requires: libgcc
|
||||||
Requires: libcap
|
Requires: libcap
|
||||||
|
|
||||||
|
%ifarch x86_64
|
||||||
|
%define rust_def_target x86_64-unknown-linux-gnu
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
|
%define rust_musl_target x86_64-unknown-linux-musl
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
%ifarch aarch64
|
||||||
|
%define rust_def_target aarch64-unknown-linux-gnu
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
|
%define rust_musl_target aarch64-unknown-linux-musl
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?using_vendored_crates}
|
||||||
|
%define cargo_offline --offline
|
||||||
|
%endif
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM. The project focuses on exclusively running modern, cloud workloads, on top of a limited set of hardware architectures and platforms. Cloud workloads refers to those that are usually run by customers inside a cloud provider. For our purposes this means modern Linux* distributions with most I/O handled by paravirtualised devices (i.e. virtio), no requirement for legacy devices and recent CPUs and KVM.
|
Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM. The project focuses on exclusively running modern, cloud workloads, on top of a limited set of hardware architectures and platforms. Cloud workloads refers to those that are usually run by customers inside a cloud provider. For our purposes this means modern Linux* distributions with most I/O handled by paravirtualised devices (i.e. virtio), no requirement for legacy devices and recent CPUs and KVM.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
|
|
||||||
%setup -q
|
%setup -q
|
||||||
|
%if 0%{?using_vendored_crates}
|
||||||
|
tar xf %{SOURCE1}
|
||||||
|
mkdir -p .cargo
|
||||||
|
cp %{SOURCE2} .cargo/
|
||||||
|
%endif
|
||||||
|
|
||||||
%install
|
%install
|
||||||
rm -rf %{buildroot}
|
rm -rf %{buildroot}
|
||||||
install -d %{buildroot}%{_bindir}
|
install -d %{buildroot}%{_bindir}
|
||||||
install -D -m755 ./target/x86_64-unknown-linux-gnu/release/cloud-hypervisor %{buildroot}%{_bindir}
|
install -D -m755 ./target/%{rust_def_target}/release/cloud-hypervisor %{buildroot}%{_bindir}
|
||||||
install -D -m755 ./target/x86_64-unknown-linux-gnu/release/ch-remote %{buildroot}%{_bindir}
|
install -D -m755 ./target/%{rust_def_target}/release/ch-remote %{buildroot}%{_bindir}
|
||||||
install -d %{buildroot}%{_libdir}
|
install -d %{buildroot}%{_libdir}
|
||||||
install -d %{buildroot}%{_libdir}/cloud-hypervisor
|
install -d %{buildroot}%{_libdir}/cloud-hypervisor
|
||||||
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor
|
install -D -m755 target/%{rust_def_target}/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor
|
||||||
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor
|
install -D -m755 target/%{rust_def_target}/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor
|
||||||
|
|
||||||
%if 0%{?using_musl_libc}
|
%if 0%{?using_musl_libc}
|
||||||
install -d %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -d %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/cloud-hypervisor %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/%{rust_musl_target}/release/cloud-hypervisor %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/%{rust_musl_target}/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/%{rust_musl_target}/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/ch-remote %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/%{rust_musl_target}/release/ch-remote %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
@@ -74,21 +103,25 @@ fi
|
|||||||
echo ${cargo_version}
|
echo ${cargo_version}
|
||||||
|
|
||||||
%if 0%{?using_rustup}
|
%if 0%{?using_rustup}
|
||||||
rustup target list --installed | grep x86_64-unknown-linux-gnu
|
rustup target list --installed | grep -e "%{rust_def_target}"
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Target x86_64-unknown-linux-gnu not found, please install(#rustup target add x86_64-unknown-linux-gnu). exiting"
|
echo "Target %{rust_def_target} not found, please install(#rustup target add %{rust_def_target}). exiting"
|
||||||
fi
|
fi
|
||||||
%if 0%{?using_musl_libc}
|
%if 0%{?using_musl_libc}
|
||||||
rustup target list --installed | grep x86_64-unknown-linux-musl
|
rustup target list --installed | grep -e "%{rust_musl_target}"
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Target x86_64-unknown-linux-musl not found, please install(#rustup target add x86_64-unknown-linux-musl). exiting"
|
echo "Target %{rust_musl_target} not found, please install(#rustup target add %{rust_musl_target}). exiting"
|
||||||
fi
|
fi
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
cargo build --release --target=x86_64-unknown-linux-gnu --all
|
%if 0%{?using_vendored_crates}
|
||||||
|
# For vendored build, prepend this so openssl-sys doesn't trigger full OpenSSL build
|
||||||
|
export OPENSSL_NO_VENDOR=1
|
||||||
|
%endif
|
||||||
|
cargo build --release --target=%{rust_def_target} --all %{cargo_offline}
|
||||||
%if 0%{?using_musl_libc}
|
%if 0%{?using_musl_libc}
|
||||||
cargo build --release --target=x86_64-unknown-linux-musl --all
|
cargo build --release --target=%{rust_musl_target} --all %{cargo_offline}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +145,18 @@ rm -rf %{buildroot}
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 25 2022 Sebastien Boeuf <sebastien.boeuf@intel.com> 24.0-0
|
||||||
|
- Update to 24.0
|
||||||
|
|
||||||
|
* Tue May 18 2022 Anatol Belski <anbelski@linux.microsoft.com> - 23.1-0
|
||||||
|
- Update to 23.1
|
||||||
|
- Add support for aarch64 build
|
||||||
|
- Add offline build configuration using vendored crates
|
||||||
|
- Fix dependency for openssl-sys
|
||||||
|
|
||||||
|
* Thu Apr 13 2022 Rob Bradford <robert.bradford@intel.com> 23.0-0
|
||||||
|
- Update to 23.0
|
||||||
|
|
||||||
* Thu Mar 03 2022 Rob Bradford <robert.bradford@intel.com> 22.0-0
|
* Thu Mar 03 2022 Rob Bradford <robert.bradford@intel.com> 22.0-0
|
||||||
- Update to 22.0
|
- Update to 22.0
|
||||||
|
|
||||||
|
|||||||
36
rpm/update_src
Normal file
36
rpm/update_src
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CH_VER=$1
|
||||||
|
CH_SPEC_DIR=$(pwd)
|
||||||
|
CH_TMP_DIR=$CH_SPEC_DIR/ch_tmp
|
||||||
|
CH_SRC_DIR=$CH_SPEC_DIR/SOURCES
|
||||||
|
|
||||||
|
if [ -z $CH_VER ]; then
|
||||||
|
echo "Replace sources with the given <version>"
|
||||||
|
echo "Usage: $0 <version>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $CH_TMP_DIR
|
||||||
|
if [ ! -d $CH_SRC_DIR ]; then
|
||||||
|
mkdir $CH_SRC_DIR
|
||||||
|
fi
|
||||||
|
rm -f $CH_SRC_DIR/v*.tar.gz $CH_SRC_DIR/config.toml $CH_SRC_DIR/vendor.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
wget https://github.com/cloud-hypervisor/cloud-hypervisor/archive/v${CH_VER}.tar.gz -O $CH_SRC_DIR/v${CH_VER}.tar.gz
|
||||||
|
mkdir $CH_TMP_DIR
|
||||||
|
tar xf $CH_SRC_DIR/v${CH_VER}.tar.gz -C $CH_TMP_DIR --strip-components=1
|
||||||
|
|
||||||
|
|
||||||
|
pushd $CH_TMP_DIR
|
||||||
|
|
||||||
|
cargo vendor > $CH_SRC_DIR/config.toml
|
||||||
|
tar czvf $CH_SRC_DIR/vendor.tar.gz vendor
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm -rf $CH_TMP_DIR
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
CLI_NAME="Cloud Hypervisor"
|
CLI_NAME="Cloud Hypervisor"
|
||||||
|
|
||||||
CTR_IMAGE_TAG="cloudhypervisor/dev"
|
CTR_IMAGE_TAG="cloudhypervisor/dev"
|
||||||
CTR_IMAGE_VERSION="20220303-0"
|
CTR_IMAGE_VERSION="20220524-0"
|
||||||
CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
|
CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
|
||||||
|
|
||||||
DOCKER_RUNTIME="docker"
|
DOCKER_RUNTIME="docker"
|
||||||
@@ -183,10 +183,9 @@ cmd_help() {
|
|||||||
echo " --volumes Hash separated volumes to be exported. Example --volumes /mnt:/mnt#/myvol:/myvol"
|
echo " --volumes Hash separated volumes to be exported. Example --volumes /mnt:/mnt#/myvol:/myvol"
|
||||||
echo " --hypervisor Underlying hypervisor. Options kvm, mshv"
|
echo " --hypervisor Underlying hypervisor. Options kvm, mshv"
|
||||||
echo ""
|
echo ""
|
||||||
echo " tests [--unit|--cargo|--all] [--libc musl|gnu] [-- [<test scripts args>] [-- [<test binary args>]]] "
|
echo " tests [<test type (see below)>] [--libc musl|gnu] [-- [<test scripts args>] [-- [<test binary args>]]] "
|
||||||
echo " Run the Cloud Hypervisor tests."
|
echo " Run the Cloud Hypervisor tests."
|
||||||
echo " --unit Run the unit tests."
|
echo " --unit Run the unit tests."
|
||||||
echo " --cargo Run the cargo tests."
|
|
||||||
echo " --integration Run the integration tests."
|
echo " --integration Run the integration tests."
|
||||||
echo " --integration-sgx Run the SGX integration tests."
|
echo " --integration-sgx Run the SGX integration tests."
|
||||||
echo " --integration-vfio Run the VFIO integration tests."
|
echo " --integration-vfio Run the VFIO integration tests."
|
||||||
@@ -227,6 +226,11 @@ cmd_build() {
|
|||||||
} ;;
|
} ;;
|
||||||
"--debug") { build="debug"; } ;;
|
"--debug") { build="debug"; } ;;
|
||||||
"--release") { build="release"; } ;;
|
"--release") { build="release"; } ;;
|
||||||
|
"--runtime")
|
||||||
|
shift
|
||||||
|
DOCKER_RUNTIME="$1"
|
||||||
|
export DOCKER_RUNTIME
|
||||||
|
;;
|
||||||
"--libc")
|
"--libc")
|
||||||
shift
|
shift
|
||||||
[[ "$1" =~ ^(musl|gnu)$ ]] ||
|
[[ "$1" =~ ^(musl|gnu)$ ]] ||
|
||||||
@@ -271,8 +275,6 @@ cmd_build() {
|
|||||||
cargo_args=("$@")
|
cargo_args=("$@")
|
||||||
[ $build = "release" ] && cargo_args+=("--release")
|
[ $build = "release" ] && cargo_args+=("--release")
|
||||||
cargo_args+=(--target "$target")
|
cargo_args+=(--target "$target")
|
||||||
[ "$(uname -m)" = "aarch64" ] && cargo_args+=("--no-default-features")
|
|
||||||
[ "$(uname -m)" = "aarch64" ] && cargo_args+=(--features "$hypervisor")
|
|
||||||
|
|
||||||
rustflags=""
|
rustflags=""
|
||||||
target_cc=""
|
target_cc=""
|
||||||
@@ -314,7 +316,6 @@ cmd_clean() {
|
|||||||
|
|
||||||
cmd_tests() {
|
cmd_tests() {
|
||||||
unit=false
|
unit=false
|
||||||
cargo=false
|
|
||||||
integration=false
|
integration=false
|
||||||
integration_sgx=false
|
integration_sgx=false
|
||||||
integration_vfio=false
|
integration_vfio=false
|
||||||
@@ -332,7 +333,6 @@ cmd_tests() {
|
|||||||
exit 1
|
exit 1
|
||||||
} ;;
|
} ;;
|
||||||
"--unit") { unit=true; } ;;
|
"--unit") { unit=true; } ;;
|
||||||
"--cargo") { cargo=true; } ;;
|
|
||||||
"--integration") { integration=true; } ;;
|
"--integration") { integration=true; } ;;
|
||||||
"--integration-sgx") { integration_sgx=true; } ;;
|
"--integration-sgx") { integration_sgx=true; } ;;
|
||||||
"--integration-vfio") { integration_vfio=true; } ;;
|
"--integration-vfio") { integration_vfio=true; } ;;
|
||||||
@@ -398,16 +398,6 @@ cmd_tests() {
|
|||||||
./scripts/run_unit_tests.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_unit_tests.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$cargo" = true ]; then
|
|
||||||
say "Running cargo tests..."
|
|
||||||
$DOCKER_RUNTIME run \
|
|
||||||
--workdir "$CTR_CLH_ROOT_DIR" \
|
|
||||||
--rm \
|
|
||||||
--volume "$CLH_ROOT_DIR:$CTR_CLH_ROOT_DIR" $exported_volumes \
|
|
||||||
"$CTR_IMAGE" \
|
|
||||||
./scripts/run_cargo_tests.sh "$@" || fix_dir_perms $? || exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$integration" = true ]; then
|
if [ "$integration" = true ]; then
|
||||||
say "Running integration tests for $target..."
|
say "Running integration tests for $target..."
|
||||||
$DOCKER_RUNTIME run \
|
$DOCKER_RUNTIME run \
|
||||||
|
|||||||
42
scripts/prepare_vdpa.sh
Executable file
42
scripts/prepare_vdpa.sh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -x
|
||||||
|
|
||||||
|
sudo apt install -y libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf git make dpkg-dev libmnl-dev pkg-config
|
||||||
|
sudo sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list
|
||||||
|
sudo apt update
|
||||||
|
apt-get source linux-image-unsigned-`uname -r`
|
||||||
|
pushd linux-azure*/drivers/vdpa/vdpa_sim/
|
||||||
|
cat <<'EOF' > Makefile
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
obj-m += vdpa_sim.o
|
||||||
|
obj-m += vdpa_sim_net.o
|
||||||
|
obj-m += vdpa_sim_blk.o
|
||||||
|
EOF
|
||||||
|
make -C /lib/modules/`uname -r`/build M=$PWD
|
||||||
|
sudo make -C /lib/modules/`uname -r`/build M=$PWD modules_install
|
||||||
|
popd
|
||||||
|
sudo depmod -a
|
||||||
|
sudo modprobe vdpa
|
||||||
|
sudo modprobe vhost_vdpa
|
||||||
|
sudo modprobe vdpa_sim
|
||||||
|
sudo modprobe vdpa_sim_blk
|
||||||
|
sudo modprobe vdpa_sim_net
|
||||||
|
# After the Jenkins builder are moved to Ubuntu 22.04, manually building and
|
||||||
|
# installing iproute2/vdpa won't be required.
|
||||||
|
# Tracked by: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/3862
|
||||||
|
git clone https://github.com/shemminger/iproute2.git
|
||||||
|
pushd iproute2
|
||||||
|
./configure
|
||||||
|
make -j
|
||||||
|
sudo make install
|
||||||
|
popd
|
||||||
|
# Create /dev/vhost-vdpa-0
|
||||||
|
sudo vdpa dev add name vdpa-blk1 mgmtdev vdpasim_blk
|
||||||
|
# Create /dev/vhost-vdpa-1
|
||||||
|
sudo vdpa dev add name vdpa-blk2 mgmtdev vdpasim_blk
|
||||||
|
# Create /dev/vhost-vdpa-2
|
||||||
|
sudo vdpa dev add name vdpa-net1 mgmtdev vdpasim_net
|
||||||
|
sudo chmod 660 /dev/vhost-vdpa-0
|
||||||
|
sudo chmod 660 /dev/vhost-vdpa-1
|
||||||
|
sudo chmod 660 /dev/vhost-vdpa-2
|
||||||
|
vdpa dev show -jp
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
source $HOME/.cargo/env
|
|
||||||
source $(dirname "$0")/test-util.sh
|
|
||||||
|
|
||||||
process_common_args "$@"
|
|
||||||
|
|
||||||
# Install cargo components
|
|
||||||
time rustup component add clippy
|
|
||||||
time rustup component add rustfmt
|
|
||||||
time which cargo-audit || cargo install cargo-audit
|
|
||||||
|
|
||||||
# Run cargo builds and checks
|
|
||||||
time cargo clippy --all-targets --all-features -- -D warnings
|
|
||||||
time cargo rustc --bin cloud-hypervisor -- -D warnings
|
|
||||||
time cargo rustc -p vhost_user_net --bin vhost_user_net -- -D warnings
|
|
||||||
time cargo test
|
|
||||||
time cargo audit
|
|
||||||
time cargo clippy --all-targets --no-default-features --features "acpi,$hypervisor" -- -D warnings
|
|
||||||
time cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,$hypervisor" -- -D warnings
|
|
||||||
time cargo clippy --all-targets --no-default-features --features "$hypervisor" -- -D warnings
|
|
||||||
time cargo rustc --bin cloud-hypervisor --no-default-features --features "$hypervisor" -- -D warnings
|
|
||||||
time cargo fmt -- --check
|
|
||||||
time cargo build --all --release
|
|
||||||
@@ -11,63 +11,6 @@ WORKLOADS_LOCK="$WORKLOADS_DIR/integration_test.lock"
|
|||||||
|
|
||||||
mkdir -p "$WORKLOADS_DIR"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
|
|
||||||
# Checkout source code of a GIT repo with specified branch and commit
|
|
||||||
# Args:
|
|
||||||
# $1: Target directory
|
|
||||||
# $2: GIT URL of the repo
|
|
||||||
# $3: Required branch
|
|
||||||
# $4: Required commit (optional)
|
|
||||||
checkout_repo() {
|
|
||||||
SRC_DIR="$1"
|
|
||||||
GIT_URL="$2"
|
|
||||||
GIT_BRANCH="$3"
|
|
||||||
GIT_COMMIT="$4"
|
|
||||||
|
|
||||||
# Check whether the local HEAD commit same as the requested commit or not.
|
|
||||||
# If commit is not specified, compare local HEAD and remote HEAD.
|
|
||||||
# Remove the folder if there is difference.
|
|
||||||
if [ -d "$SRC_DIR" ]; then
|
|
||||||
pushd $SRC_DIR
|
|
||||||
git fetch
|
|
||||||
SRC_LOCAL_COMMIT=$(git rev-parse HEAD)
|
|
||||||
if [ -z "$GIT_COMMIT" ]; then
|
|
||||||
GIT_COMMIT=$(git rev-parse remotes/origin/"$GIT_BRANCH")
|
|
||||||
fi
|
|
||||||
popd
|
|
||||||
if [ "$SRC_LOCAL_COMMIT" != "$GIT_COMMIT" ]; then
|
|
||||||
rm -rf "$SRC_DIR"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Checkout the specified branch and commit (if required)
|
|
||||||
if [ ! -d "$SRC_DIR" ]; then
|
|
||||||
git clone --depth 1 "$GIT_URL" -b "$GIT_BRANCH" "$SRC_DIR"
|
|
||||||
if [ "$GIT_COMMIT" ]; then
|
|
||||||
pushd "$SRC_DIR"
|
|
||||||
git fetch --depth 1 origin "$GIT_COMMIT"
|
|
||||||
git reset --hard FETCH_HEAD
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
build_custom_linux() {
|
|
||||||
SRCDIR=$PWD
|
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
|
||||||
LINUX_CUSTOM_BRANCH="ch-5.15.12"
|
|
||||||
LINUX_CUSTOM_URL="https://github.com/cloud-hypervisor/linux.git"
|
|
||||||
|
|
||||||
checkout_repo "$LINUX_CUSTOM_DIR" "$LINUX_CUSTOM_URL" "$LINUX_CUSTOM_BRANCH"
|
|
||||||
|
|
||||||
cp $SRCDIR/resources/linux-config-aarch64 $LINUX_CUSTOM_DIR/.config
|
|
||||||
|
|
||||||
pushd $LINUX_CUSTOM_DIR
|
|
||||||
time make -j `nproc`
|
|
||||||
cp arch/arm64/boot/Image "$WORKLOADS_DIR/" || exit 1
|
|
||||||
cp arch/arm64/boot/Image.gz "$WORKLOADS_DIR/" || exit 1
|
|
||||||
popd
|
|
||||||
}
|
|
||||||
|
|
||||||
build_edk2() {
|
build_edk2() {
|
||||||
EDK2_BUILD_DIR="$WORKLOADS_DIR/edk2_build"
|
EDK2_BUILD_DIR="$WORKLOADS_DIR/edk2_build"
|
||||||
EDK2_REPO="https://github.com/tianocore/edk2.git"
|
EDK2_REPO="https://github.com/tianocore/edk2.git"
|
||||||
@@ -92,33 +35,61 @@ build_edk2() {
|
|||||||
checkout_repo "$EDK2_PLAT_DIR" "$EDK2_PLAT_REPO" master "8227e9e9f6a8aefbd772b40138f835121ccb2307"
|
checkout_repo "$EDK2_PLAT_DIR" "$EDK2_PLAT_REPO" master "8227e9e9f6a8aefbd772b40138f835121ccb2307"
|
||||||
checkout_repo "$ACPICA_DIR" "$ACPICA_REPO" master "b9c69f81a05c45611c91ea9cbce8756078d76233"
|
checkout_repo "$ACPICA_DIR" "$ACPICA_REPO" master "b9c69f81a05c45611c91ea9cbce8756078d76233"
|
||||||
|
|
||||||
pushd "$EDK2_BUILD_DIR"
|
if [[ ! -f "$EDK2_DIR/.built" || \
|
||||||
# Build
|
! -f "$EDK2_PLAT_DIR/.built" || \
|
||||||
make -C acpica -j `nproc`
|
! -f "$ACPICA_DIR/.built" ]]; then
|
||||||
source edk2/edksetup.sh
|
pushd "$EDK2_BUILD_DIR"
|
||||||
make -C edk2/BaseTools -j `nproc`
|
# Build
|
||||||
build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtCloudHv.dsc -b RELEASE -n 0
|
make -C acpica -j `nproc`
|
||||||
cp Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd "$WORKLOADS_DIR"
|
source edk2/edksetup.sh
|
||||||
popd
|
make -C edk2/BaseTools -j `nproc`
|
||||||
|
build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtCloudHv.dsc -b RELEASE -n 0
|
||||||
|
cp Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd "$WORKLOADS_DIR"
|
||||||
|
touch "$EDK2_DIR"/.built
|
||||||
|
touch "$EDK2_PLAT_DIR"/.built
|
||||||
|
touch "$ACPICA_DIR"/.built
|
||||||
|
popd
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
build_spdk_nvme() {
|
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"
|
||||||
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "f9c496b8e21a8f499df268818bf8b5d8e2b19f04"
|
SPDK_DEPLOY_DIR="/usr/local/bin/spdk-nvme"
|
||||||
|
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "6301f8915de32baed10dba1eebed556a6749211a"
|
||||||
|
|
||||||
pushd $SPDK_DIR
|
if [ ! -f "$SPDK_DIR/.built" ]; then
|
||||||
git submodule update --init
|
pushd $SPDK_DIR
|
||||||
apt-get update
|
git submodule update --init
|
||||||
./scripts/pkgdep.sh
|
apt-get update
|
||||||
./configure --with-vfio-user
|
./scripts/pkgdep.sh
|
||||||
chmod +x /usr/local/lib/python3.8/dist-packages/ninja/data/bin/ninja
|
./configure --with-vfio-user
|
||||||
make -j `nproc`
|
chmod +x /usr/local/lib/python3.8/dist-packages/ninja/data/bin/ninja
|
||||||
mkdir /usr/local/bin/spdk-nvme
|
make -j `nproc` || exit 1
|
||||||
cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme
|
touch .built
|
||||||
cp ./scripts/rpc.py /usr/local/bin/spdk-nvme
|
popd
|
||||||
cp -r ./scripts/rpc /usr/local/bin/spdk-nvme
|
fi
|
||||||
popd
|
if [ ! -d "/usr/local/bin/spdk-nvme" ]; then
|
||||||
|
mkdir -p $SPDK_DEPLOY_DIR
|
||||||
|
fi
|
||||||
|
cp "$WORKLOADS_DIR/spdk/build/bin/nvmf_tgt" $SPDK_DEPLOY_DIR/nvmf_tgt
|
||||||
|
cp "$WORKLOADS_DIR/spdk/scripts/rpc.py" $SPDK_DEPLOY_DIR/rpc.py
|
||||||
|
cp -r "$WORKLOADS_DIR/spdk/scripts/rpc" $SPDK_DEPLOY_DIR/rpc
|
||||||
|
}
|
||||||
|
|
||||||
|
build_virtiofsd() {
|
||||||
|
VIRTIOFSD_DIR="$WORKLOADS_DIR/virtiofsd_build"
|
||||||
|
VIRTIOFSD_REPO="https://gitlab.com/virtio-fs/virtiofsd.git"
|
||||||
|
|
||||||
|
checkout_repo "$VIRTIOFSD_DIR" "$VIRTIOFSD_REPO" v1.1.0 "220405d7a2606c92636d31992b5cb3036a41047b"
|
||||||
|
|
||||||
|
if [ ! -f "$VIRTIOFSD_DIR/.built" ]; then
|
||||||
|
pushd $VIRTIOFSD_DIR
|
||||||
|
time cargo build --release
|
||||||
|
cp target/release/virtiofsd "$WORKLOADS_DIR/" || exit 1
|
||||||
|
touch .built
|
||||||
|
popd
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
update_workloads() {
|
update_workloads() {
|
||||||
@@ -169,6 +140,24 @@ update_workloads() {
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.raw"
|
||||||
|
JAMMY_OS_RAW_IMAGE_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_RAW_IMAGE_NAME"
|
||||||
|
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
|
||||||
|
if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $JAMMY_OS_RAW_IMAGE_DOWNLOAD_URL || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.qcow2"
|
||||||
|
JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
|
||||||
|
JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
|
||||||
|
if [ ! -f "$JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
ALPINE_MINIROOTFS_URL="http://dl-cdn.alpinelinux.org/alpine/v3.11/releases/aarch64/alpine-minirootfs-3.11.3-aarch64.tar.gz"
|
ALPINE_MINIROOTFS_URL="http://dl-cdn.alpinelinux.org/alpine/v3.11/releases/aarch64/alpine-minirootfs-3.11.3-aarch64.tar.gz"
|
||||||
ALPINE_MINIROOTFS_TARBALL="$WORKLOADS_DIR/alpine-minirootfs-aarch64.tar.gz"
|
ALPINE_MINIROOTFS_TARBALL="$WORKLOADS_DIR/alpine-minirootfs-aarch64.tar.gz"
|
||||||
if [ ! -f "$ALPINE_MINIROOTFS_TARBALL" ]; then
|
if [ ! -f "$ALPINE_MINIROOTFS_TARBALL" ]; then
|
||||||
@@ -203,6 +192,15 @@ update_workloads() {
|
|||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
|
LAST_RELEASE_VERSION="v23.0"
|
||||||
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
||||||
|
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $CH_RELEASE_URL -O "$CH_RELEASE_NAME" || exit 1
|
||||||
|
chmod +x $CH_RELEASE_NAME
|
||||||
|
popd
|
||||||
|
|
||||||
# Build custom kernel for guest VMs
|
# Build custom kernel for guest VMs
|
||||||
build_custom_linux
|
build_custom_linux
|
||||||
|
|
||||||
@@ -217,19 +215,7 @@ update_workloads() {
|
|||||||
guestunmount "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR"
|
guestunmount "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR"
|
||||||
|
|
||||||
# Build virtiofsd
|
# Build virtiofsd
|
||||||
VIRTIOFSD="$WORKLOADS_DIR/virtiofsd"
|
build_virtiofsd
|
||||||
VIRTIOFSD_DIR="virtiofsd_build"
|
|
||||||
if [ ! -f "$VIRTIOFSD" ]; then
|
|
||||||
pushd $WORKLOADS_DIR
|
|
||||||
git clone "https://gitlab.com/virtio-fs/virtiofsd.git" $VIRTIOFSD_DIR
|
|
||||||
pushd $VIRTIOFSD_DIR
|
|
||||||
git checkout v1.1.0
|
|
||||||
time cargo build --release
|
|
||||||
cp target/release/virtiofsd $VIRTIOFSD || exit 1
|
|
||||||
popd
|
|
||||||
rm -rf $VIRTIOFSD_DIR
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
|
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
|
||||||
MNT_DIR="mount_image"
|
MNT_DIR="mount_image"
|
||||||
@@ -252,10 +238,10 @@ update_workloads() {
|
|||||||
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# checkout and build SPDK NVMe
|
# Checkout and build SPDK NVMe
|
||||||
build_spdk_nvme
|
build_spdk_nvme
|
||||||
|
|
||||||
# Check and build EDK2 binary
|
# Checkout and build EDK2
|
||||||
build_edk2
|
build_edk2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,15 @@ if [ $? -ne 0 ]; then
|
|||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
|
LAST_RELEASE_VERSION="v23.0"
|
||||||
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
||||||
|
CH_RELEASE_NAME="cloud-hypervisor-static"
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $CH_RELEASE_URL -O "$CH_RELEASE_NAME" || exit 1
|
||||||
|
chmod +x $CH_RELEASE_NAME
|
||||||
|
popd
|
||||||
|
|
||||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,23 @@ if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20220329-0.qcow2"
|
||||||
|
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
|
||||||
|
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
|
||||||
|
if [ ! -f "$JAMMY_OS_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $JAMMY_OS_IMAGE_URL || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20220329-0.raw"
|
||||||
|
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
|
||||||
|
if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time qemu-img convert -p -f qcow2 -O raw $JAMMY_OS_IMAGE_NAME $JAMMY_OS_RAW_IMAGE_NAME || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
ALPINE_MINIROOTFS_URL="http://dl-cdn.alpinelinux.org/alpine/v3.11/releases/x86_64/alpine-minirootfs-3.11.3-x86_64.tar.gz"
|
ALPINE_MINIROOTFS_URL="http://dl-cdn.alpinelinux.org/alpine/v3.11/releases/x86_64/alpine-minirootfs-3.11.3-x86_64.tar.gz"
|
||||||
ALPINE_MINIROOTFS_TARBALL="$WORKLOADS_DIR/alpine-minirootfs-x86_64.tar.gz"
|
ALPINE_MINIROOTFS_TARBALL="$WORKLOADS_DIR/alpine-minirootfs-x86_64.tar.gz"
|
||||||
if [ ! -f "$ALPINE_MINIROOTFS_TARBALL" ]; then
|
if [ ! -f "$ALPINE_MINIROOTFS_TARBALL" ]; then
|
||||||
@@ -107,27 +124,7 @@ popd
|
|||||||
|
|
||||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||||
|
build_custom_linux
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
|
||||||
|
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|
||||||
SRCDIR=$PWD
|
|
||||||
pushd $WORKLOADS_DIR
|
|
||||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.15.12" $LINUX_CUSTOM_DIR
|
|
||||||
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|
||||||
pushd $LINUX_CUSTOM_DIR
|
|
||||||
time make bzImage -j `nproc`
|
|
||||||
cp vmlinux $VMLINUX_IMAGE || exit 1
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$LINUX_CUSTOM_DIR" ]; then
|
|
||||||
rm -rf $LINUX_CUSTOM_DIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
VIRTIOFSD="$WORKLOADS_DIR/virtiofsd"
|
VIRTIOFSD="$WORKLOADS_DIR/virtiofsd"
|
||||||
VIRTIOFSD_DIR="virtiofsd_build"
|
VIRTIOFSD_DIR="virtiofsd_build"
|
||||||
@@ -190,10 +187,13 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
|
|||||||
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||||
|
|
||||||
# Both test_vfio and ovs-dpdk rely on hugepages
|
# Both test_vfio, ovs-dpdk and vDPA tests rely on hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
|
# Update max locked memory to 'unlimited' to avoid issues with vDPA
|
||||||
|
ulimit -l unlimited
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test $features "parallel::$test_filter" -- ${test_binary_args[*]}
|
time cargo test $features "parallel::$test_filter" -- ${test_binary_args[*]}
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|||||||
@@ -4,23 +4,45 @@ 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}
|
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"
|
||||||
|
|
||||||
|
build_fio() {
|
||||||
|
FIO_DIR="$WORKLOADS_DIR/fio_build"
|
||||||
|
FIO_REPO="https://github.com/axboe/fio.git"
|
||||||
|
|
||||||
|
checkout_repo "$FIO_DIR" "$FIO_REPO" master "1953e1adb5a28ed21370e85991d7f5c3cdc699f3"
|
||||||
|
if [ ! -f "$FIO_DIR/.built" ]; then
|
||||||
|
pushd $FIO_DIR
|
||||||
|
./configure
|
||||||
|
make -j `nproc`
|
||||||
|
cp fio "$WORKLOADS_DIR/fio"
|
||||||
|
touch .built
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
|
|
||||||
# For now these values are default for kvm
|
# For now these values are default for kvm
|
||||||
features=""
|
features=""
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ]; then
|
||||||
features="--no-default-features --features mshv,common"
|
features="--no-default-features --features mshv,common"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
cp scripts/sha1sums-${TEST_ARCH} $WORKLOADS_DIR
|
||||||
|
|
||||||
|
if [ ${TEST_ARCH} == "aarch64" ]; then
|
||||||
|
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-arm64-custom-20210929-0.qcow2"
|
||||||
|
else
|
||||||
|
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
|
||||||
|
fi
|
||||||
|
|
||||||
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
|
|
||||||
FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
|
FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
|
||||||
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
||||||
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
||||||
@@ -29,7 +51,12 @@ if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
|
if [ ${TEST_ARCH} == "aarch64" ]; then
|
||||||
|
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-arm64-custom-20210929-0.raw"
|
||||||
|
else
|
||||||
|
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
|
||||||
|
fi
|
||||||
|
|
||||||
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
|
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
|
||||||
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
@@ -38,43 +65,38 @@ if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
grep focal sha1sums-x86_64 | sha1sum --check
|
grep focal sha1sums-${TEST_ARCH} | sha1sum --check
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "sha1sum validation of images failed, remove invalid images to fix the issue."
|
echo "sha1sum validation of images failed, remove invalid images to fix the issue."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
if [ ${TEST_ARCH} == "aarch64" ]; then
|
||||||
|
build_fio
|
||||||
|
|
||||||
|
# Update the fio in the cloud image to use io_uring on AArch64
|
||||||
|
FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_NAME="focal-server-cloudimg-arm64-custom-20210929-0-update-tool.raw"
|
||||||
|
cp "$FOCAL_OS_RAW_IMAGE" "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_NAME"
|
||||||
|
FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR="$WORKLOADS_DIR/focal-server-cloudimg-root"
|
||||||
|
if [ ! -d "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" ]; then
|
||||||
|
mkdir -p "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR"
|
||||||
|
fi
|
||||||
|
# Mount the 'raw' image, replace the fio and umount the working folder
|
||||||
|
guestmount -a "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_NAME" -m /dev/sda1 "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" || exit 1
|
||||||
|
cp "$WORKLOADS_DIR"/fio "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR"/usr/bin/fio
|
||||||
|
guestunmount "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR"
|
||||||
|
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
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
build_custom_linux
|
||||||
|
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
BUILD_TARGET="${TEST_ARCH}-unknown-linux-${CH_LIBC}"
|
||||||
|
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|
||||||
SRCDIR=$PWD
|
|
||||||
pushd $WORKLOADS_DIR
|
|
||||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.15.12" $LINUX_CUSTOM_DIR
|
|
||||||
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
|
||||||
pushd $LINUX_CUSTOM_DIR
|
|
||||||
time make bzImage -j `nproc`
|
|
||||||
cp vmlinux $VMLINUX_IMAGE || exit 1
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$LINUX_CUSTOM_DIR" ]; then
|
|
||||||
rm -rf $LINUX_CUSTOM_DIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
TARGET_CC=""
|
||||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "${TEST_ARCH}-unknown-linux-musl" ]]; then
|
||||||
TARGET_CC="musl-gcc"
|
TARGET_CC="musl-gcc"
|
||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/${TEST_ARCH}-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --all --release $features --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
@@ -87,6 +109,10 @@ strip target/$BUILD_TARGET/release/performance-metrics
|
|||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
|
if [ -n "$test_filter" ]; then
|
||||||
|
test_binary_args+=("--test-filter $test_filter")
|
||||||
|
fi
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time target/$BUILD_TARGET/release/performance-metrics ${test_binary_args[*]}
|
time target/$BUILD_TARGET/release/performance-metrics ${test_binary_args[*]}
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
|
|
||||||
BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
||||||
cargo_args=("")
|
cargo_args=("")
|
||||||
|
|
||||||
if [[ $(uname -m) = "aarch64" || $hypervisor = "mshv" ]]; then
|
if [[ $hypervisor = "mshv" ]]; then
|
||||||
cargo_args+=("--no-default-features")
|
cargo_args+=("--no-default-features")
|
||||||
cargo_args+=("--features $hypervisor")
|
cargo_args+=("--features common,$hypervisor")
|
||||||
|
elif [[ $(uname -m) = "x86_64" ]]; then
|
||||||
|
cargo_args+=("--features tdx")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||||
@@ -19,4 +21,4 @@ if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
|||||||
fi
|
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
|
||||||
|
|||||||
@@ -4,3 +4,5 @@
|
|||||||
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
|
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
|
||||||
25b4f9ac308898d63b73d7db0e0e2d4768853723 focal-server-cloudimg-arm64-custom-20210929-0.qcow2
|
25b4f9ac308898d63b73d7db0e0e2d4768853723 focal-server-cloudimg-arm64-custom-20210929-0.qcow2
|
||||||
9953b31bb1923cdd8d91b1b7cc9ad3a9be1e0a59 focal-server-cloudimg-arm64-custom-20210929-0.raw
|
9953b31bb1923cdd8d91b1b7cc9ad3a9be1e0a59 focal-server-cloudimg-arm64-custom-20210929-0.raw
|
||||||
|
7118f4d4cad18c8357bc2ad9824a50f9a82a860a jammy-server-cloudimg-arm64-custom-20220329-0.qcow2
|
||||||
|
1f2b71be43b8f748f01306c4454e5c921343faa4 jammy-server-cloudimg-arm64-custom-20220329-0.raw
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user