mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
378 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
487a43cdee | ||
|
|
96df501b7f | ||
|
|
e0e3779e96 | ||
|
|
66c40b0f02 | ||
|
|
a0c8bf4f9f | ||
|
|
02e1c54426 | ||
|
|
3d82867fe2 | ||
|
|
193950ce42 | ||
|
|
548a5234c5 | ||
|
|
bcb411b4d6 | ||
|
|
2c1772b401 | ||
|
|
363b478040 | ||
|
|
a00d29867c | ||
|
|
6ee7bfdd50 | ||
|
|
d926db5ef8 | ||
|
|
376b676910 | ||
|
|
219716c3f1 | ||
|
|
3bb26093eb | ||
|
|
06dc708515 | ||
|
|
70cfd1be67 | ||
|
|
6b79aca32d | ||
|
|
0149e65081 | ||
|
|
ecf3db5092 | ||
|
|
8cd40a7a80 | ||
|
|
c559f52fe5 | ||
|
|
f022953fff | ||
|
|
442ac9056c | ||
|
|
fe97785a9f | ||
|
|
e5bb3903ad | ||
|
|
0b6bc75d3a | ||
|
|
9da7435f06 | ||
|
|
3225c0c7c8 | ||
|
|
c03f3b54b6 | ||
|
|
ba5af92984 | ||
|
|
c74be069b5 | ||
|
|
b29d9607df | ||
|
|
c0c4c0f712 | ||
|
|
1c16428e4d | ||
|
|
1649845944 | ||
|
|
6372635195 | ||
|
|
dd09a0a890 | ||
|
|
b56e721d78 | ||
|
|
39f1c5f476 | ||
|
|
92cf2816b0 | ||
|
|
83c8c3c913 | ||
|
|
922bc0d9aa | ||
|
|
d760a77fbb | ||
|
|
ad8cdb5e85 | ||
|
|
889d06277a | ||
|
|
e3fc5c83bb | ||
|
|
06dc25cbd6 | ||
|
|
4ef388b67c | ||
|
|
5ffc6d6107 | ||
|
|
e98ea329bf | ||
|
|
081a6ebb51 | ||
|
|
ffe78c98fd | ||
|
|
741d640330 | ||
|
|
447cad3861 | ||
|
|
47fbe9af1e | ||
|
|
3f87a81e2b | ||
|
|
aeae5255c8 | ||
|
|
0039f45276 | ||
|
|
b792d4751d | ||
|
|
dc6c3a249d | ||
|
|
4c7cf634b9 | ||
|
|
69bd0036d9 | ||
|
|
87d81dd2b1 | ||
|
|
f03c3b737f | ||
|
|
f346687e3d | ||
|
|
953c238544 | ||
|
|
9ea052785e | ||
|
|
10c33ab257 | ||
|
|
14af5e1679 | ||
|
|
8ab2d5e539 | ||
|
|
63226e2b80 | ||
|
|
d0dbc7fb4d | ||
|
|
aac614e2ec | ||
|
|
9abf8d6868 | ||
|
|
6fdba7ca11 | ||
|
|
d2e42a0ed4 | ||
|
|
3e4d6a4081 | ||
|
|
7f18d0a281 | ||
|
|
99d42bb05e | ||
|
|
dbce6cb1ce | ||
|
|
cbc5e8da4a | ||
|
|
a3ddc2779d | ||
|
|
99353856ef | ||
|
|
d99c0c0d1d | ||
|
|
8e9ce3ab7c | ||
|
|
3acb988c1a | ||
|
|
ef67eab8c3 | ||
|
|
569a2a5f07 | ||
|
|
353c17eb4d | ||
|
|
3166f22751 | ||
|
|
b4376a0dd9 | ||
|
|
d813c45d81 | ||
|
|
aa13ede316 | ||
|
|
d1d9e7b241 | ||
|
|
d86e2ce34d | ||
|
|
b6d009830d | ||
|
|
2f70800e91 | ||
|
|
33f3a456c7 | ||
|
|
68ce3a9222 | ||
|
|
efb579b224 | ||
|
|
0ff6cdf5eb | ||
|
|
25c0c55bb5 | ||
|
|
6e0e632361 | ||
|
|
1c9df58440 | ||
|
|
1917e86206 | ||
|
|
787f5085b6 | ||
|
|
fec39ccf51 | ||
|
|
115085eb9e | ||
|
|
802e9009b9 | ||
|
|
37fbece885 | ||
|
|
ec6e87479f | ||
|
|
5b51024ef7 | ||
|
|
99a98f270d | ||
|
|
c0af33a4c9 | ||
|
|
0cf868b5c1 | ||
|
|
3da60dfa5e | ||
|
|
1c8a91940e | ||
|
|
8c117a8117 | ||
|
|
7d0aa1fd02 | ||
|
|
a0190b16aa | ||
|
|
1bd8eb68ff | ||
|
|
8363eddd97 | ||
|
|
70aa5bc231 | ||
|
|
b8ce1816e9 | ||
|
|
43eed4861f | ||
|
|
268c4ea214 | ||
|
|
29a0ddc58e | ||
|
|
4079e4f1ad | ||
|
|
fba0b5f93c | ||
|
|
05cc5f596c | ||
|
|
c1b33329db | ||
|
|
402a24a688 | ||
|
|
0809e7f675 | ||
|
|
a718716831 | ||
|
|
5a9dd7489c | ||
|
|
dec8d619d4 | ||
|
|
c39cdb3c1f | ||
|
|
26ae8b6d5c | ||
|
|
de31b3fadc | ||
|
|
b06ad85604 | ||
|
|
8d89736c68 | ||
|
|
55ee8eb482 | ||
|
|
1017157bb6 | ||
|
|
499989fb17 | ||
|
|
ce0f30bb54 | ||
|
|
fce202a90c | ||
|
|
95626ae564 | ||
|
|
1e1012c31b | ||
|
|
56207dc3a0 | ||
|
|
57fdaa3a39 | ||
|
|
19c5c0af9f | ||
|
|
e26e7b4d72 | ||
|
|
e8d6c9ecb0 | ||
|
|
0712027eb1 | ||
|
|
7ea5d7a416 | ||
|
|
7023d4ff84 | ||
|
|
5f31ad319e | ||
|
|
5083549afe | ||
|
|
beed5e5d6d | ||
|
|
7feb25daf0 | ||
|
|
f2574897cd | ||
|
|
2698924c0d | ||
|
|
6bd4927d11 | ||
|
|
f485922b78 | ||
|
|
1faaa2cd0a | ||
|
|
6c630f4908 | ||
|
|
3b39c41a01 | ||
|
|
309e346c4c | ||
|
|
3f6833b315 | ||
|
|
a862c804ba | ||
|
|
83914d80a2 | ||
|
|
a7aecb5eee | ||
|
|
a64d27f841 | ||
|
|
7a458d85d1 | ||
|
|
a92d852848 | ||
|
|
0664647109 | ||
|
|
f2c813e1cf | ||
|
|
f00df25d40 | ||
|
|
c016a0d4d3 | ||
|
|
5c96fbb19b | ||
|
|
b955f09b80 | ||
|
|
79ad6f8536 | ||
|
|
be4f04a906 | ||
|
|
f8415debe9 | ||
|
|
9014a5e59c | ||
|
|
612621bb46 | ||
|
|
18e1d2caf5 | ||
|
|
4be406a308 | ||
|
|
7bf2a2c382 | ||
|
|
7df80220ec | ||
|
|
84d2511de0 | ||
|
|
374263ddac | ||
|
|
7b76b6b61e | ||
|
|
e06f12673b | ||
|
|
89e658d9ff | ||
|
|
5ac68534b1 | ||
|
|
6acceaa87c | ||
|
|
a3898fd8e1 | ||
|
|
7026622c24 | ||
|
|
41e5384f15 | ||
|
|
681a30bd15 | ||
|
|
1976157761 | ||
|
|
0b1e626fe3 | ||
|
|
79bc42f3c2 | ||
|
|
eca75dcfc9 | ||
|
|
600d1664ee | ||
|
|
e6208d1c0e | ||
|
|
cf635c64d7 | ||
|
|
42ca292dce | ||
|
|
b7338c96eb | ||
|
|
bf4af14e73 | ||
|
|
24a3505f0b | ||
|
|
20f3691474 | ||
|
|
c56a3ce59a | ||
|
|
18f7a37b48 | ||
|
|
98496434b9 | ||
|
|
0b2994a6e3 | ||
|
|
553e6857bd | ||
|
|
083ce323c0 | ||
|
|
8fff4c1af3 | ||
|
|
35ecfb6ec5 | ||
|
|
a61a013311 | ||
|
|
b509fd94cd | ||
|
|
631af8a4f7 | ||
|
|
aa14fe214a | ||
|
|
45e3f49bba | ||
|
|
03db406645 | ||
|
|
ba1e89139a | ||
|
|
21d40d7489 | ||
|
|
c90a0ffff6 | ||
|
|
dc7931f592 | ||
|
|
841627f10a | ||
|
|
97fdb65012 | ||
|
|
d17d70fae1 | ||
|
|
71d1296d09 | ||
|
|
0d58e51a3a | ||
|
|
97012c511d | ||
|
|
c10e2a79b1 | ||
|
|
f3870ae638 | ||
|
|
3c0b389c82 | ||
|
|
9881c94f84 | ||
|
|
ceb8151747 | ||
|
|
2554f2a8d4 | ||
|
|
036af673e6 | ||
|
|
990362e314 | ||
|
|
83d57d3cce | ||
|
|
a0babfb9c1 | ||
|
|
3394a59466 | ||
|
|
f8e0376f6d | ||
|
|
6379074264 | ||
|
|
5dbc72948f | ||
|
|
04d111ee15 | ||
|
|
a9623c7a28 | ||
|
|
4baf85857a | ||
|
|
e3d2917d5f | ||
|
|
a84b540b65 | ||
|
|
8eb162e3d7 | ||
|
|
2804608a1c | ||
|
|
e0125653b1 | ||
|
|
e431a48201 | ||
|
|
c143cb3af0 | ||
|
|
b6feae0ace | ||
|
|
520aff2efc | ||
|
|
41880919a0 | ||
|
|
865291d840 | ||
|
|
346ee09e6b | ||
|
|
59012ccc6e | ||
|
|
3f17f4657b | ||
|
|
086ca9b935 | ||
|
|
9b724303ac | ||
|
|
948573db0d | ||
|
|
0352846af2 | ||
|
|
8b3f0043b0 | ||
|
|
9d532acab6 | ||
|
|
df2a7c1764 | ||
|
|
3f5dac988f | ||
|
|
3096f1d42f | ||
|
|
42a4e593ce | ||
|
|
b56da6ee24 | ||
|
|
90dcbc3232 | ||
|
|
f3522e85fc | ||
|
|
d3ac6a85e0 | ||
|
|
38a1b45783 | ||
|
|
e9841db486 | ||
|
|
c1f555cde3 | ||
|
|
505f4dfa53 | ||
|
|
67ad3ff1ba | ||
|
|
755cabea4c | ||
|
|
1ed4898d28 | ||
|
|
a807b91f86 | ||
|
|
f6236087d8 | ||
|
|
95f83320b1 | ||
|
|
dcc858a403 | ||
|
|
57ea412c64 | ||
|
|
e32c9525c0 | ||
|
|
2b4f60e57b | ||
|
|
5736205cf0 | ||
|
|
a8d1849485 | ||
|
|
55937f63bc | ||
|
|
426d5d6dd0 | ||
|
|
3f3d07b3dc | ||
|
|
296cb909f4 | ||
|
|
e7d52fc736 | ||
|
|
a598b935f2 | ||
|
|
1c0b6f1090 | ||
|
|
1b12790c13 | ||
|
|
bd307dcab5 | ||
|
|
83d757d89a | ||
|
|
1b8e7ac06c | ||
|
|
389e4fe8be | ||
|
|
06a9c3b839 | ||
|
|
36cf46e381 | ||
|
|
1efdea7466 | ||
|
|
e662a2e12c | ||
|
|
5496bd5dfb | ||
|
|
e655de1e39 | ||
|
|
a55a642b70 | ||
|
|
ded8959b9a | ||
|
|
53e49636ca | ||
|
|
0b0f3c69f0 | ||
|
|
6650f553bd | ||
|
|
c5bca514b9 | ||
|
|
c4106c0592 | ||
|
|
61f89e7dcc | ||
|
|
7a4be1534f | ||
|
|
cf0c4e07b6 | ||
|
|
36ec53c4a0 | ||
|
|
c7997ea4e5 | ||
|
|
b2d3aba19c | ||
|
|
9cd97bb64e | ||
|
|
868fdf9dfe | ||
|
|
12729eb034 | ||
|
|
a062401be6 | ||
|
|
09cc139b53 | ||
|
|
4635ebd4b2 | ||
|
|
ca96ff601b | ||
|
|
feb523ef78 | ||
|
|
7e47464a48 | ||
|
|
4c4f79c831 | ||
|
|
0fd701ac75 | ||
|
|
64924d5c2b | ||
|
|
9c11927305 | ||
|
|
b13d0e53c5 | ||
|
|
6001240ca1 | ||
|
|
9534604ef3 | ||
|
|
c152f9f6bc | ||
|
|
325e62372d | ||
|
|
9421884334 | ||
|
|
fcd09946b7 | ||
|
|
a20e481abe | ||
|
|
6e4374c392 | ||
|
|
44452cbe22 | ||
|
|
7b2ebd2fa5 | ||
|
|
8a0f6014ce | ||
|
|
d78da5d252 | ||
|
|
b35a94d83c | ||
|
|
961319d8ad | ||
|
|
b97f929706 | ||
|
|
b71564f284 | ||
|
|
f2be30f699 | ||
|
|
b14216e854 | ||
|
|
3498e67bda | ||
|
|
24d163b244 | ||
|
|
90697d4ae0 | ||
|
|
73c4156775 | ||
|
|
02f774824b | ||
|
|
74cd3d0dc2 | ||
|
|
85962099c7 | ||
|
|
04ee1efa70 | ||
|
|
5258a870e0 | ||
|
|
76d6d28f3e | ||
|
|
5132e3b907 | ||
|
|
599c5280ed | ||
|
|
2f649bb6ad |
5
.github/workflows/build.yaml
vendored
5
.github/workflows/build.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
- "1.62"
|
- "1.64"
|
||||||
target:
|
target:
|
||||||
- x86_64-unknown-linux-gnu
|
- x86_64-unknown-linux-gnu
|
||||||
- x86_64-unknown-linux-musl
|
- x86_64-unknown-linux-musl
|
||||||
@@ -42,6 +42,9 @@ jobs:
|
|||||||
- name: Build (default features + tdx)
|
- name: Build (default features + tdx)
|
||||||
run: cargo rustc --locked --bin cloud-hypervisor --features "tdx" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
run: cargo rustc --locked --bin cloud-hypervisor --features "tdx" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
|
- name: Build (default features + dbus_api)
|
||||||
|
run: cargo rustc --locked --bin cloud-hypervisor --features "dbus_api" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
- name: Build (default features + guest_debug)
|
- name: Build (default features + guest_debug)
|
||||||
run: cargo rustc --locked --bin cloud-hypervisor --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
run: cargo rustc --locked --bin cloud-hypervisor --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||||
|
|
||||||
|
|||||||
20
.github/workflows/docker-image.yaml
vendored
20
.github/workflows/docker-image.yaml
vendored
@@ -7,6 +7,10 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths: resources/Dockerfile
|
paths: resources/Dockerfile
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -20,19 +24,19 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to ghcr
|
||||||
if: ${{ github.event_name == 'push' }}
|
uses: docker/login-action@v2
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
registry: ${{ env.REGISTRY }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
# list of Docker images to use as base name for tags
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
images: cloudhypervisor/dev
|
|
||||||
# generate Docker tags based on the following events/attributes
|
# generate Docker tags based on the following events/attributes
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,value={{date 'YYYYMMDD'}}-0
|
type=raw,value={{date 'YYYYMMDD'}}-0
|
||||||
|
|||||||
26
.github/workflows/hadolint.yaml
vendored
Normal file
26
.github/workflows/hadolint.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Lint Dockerfile
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- resources/Dockerfile
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- resources/Dockerfile
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
hadolint:
|
||||||
|
name: Run Hadolint Dockerfile Linter
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Lint Dockerfile
|
||||||
|
uses: hadolint/hadolint-action@master
|
||||||
|
with:
|
||||||
|
dockerfile: ./resources/Dockerfile
|
||||||
|
format: tty
|
||||||
|
no-fail: false
|
||||||
|
verbose: true
|
||||||
|
failure-threshold: info
|
||||||
14
.github/workflows/release.yaml
vendored
14
.github/workflows/release.yaml
vendored
@@ -16,29 +16,29 @@ 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: "1.62"
|
toolchain: "1.67.1"
|
||||||
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: "1.62"
|
toolchain: "1.67.1"
|
||||||
target: x86_64-unknown-linux-musl
|
target: x86_64-unknown-linux-musl
|
||||||
- name: Build
|
- name: Build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
toolchain: "1.62"
|
toolchain: "1.67.1"
|
||||||
command: build
|
command: build
|
||||||
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-gnu
|
args: --all --release --features mshv --target=x86_64-unknown-linux-gnu
|
||||||
- name: Static Build
|
- name: Static Build
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
toolchain: "1.62"
|
toolchain: "1.67.1"
|
||||||
command: build
|
command: build
|
||||||
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-musl
|
args: --all --release --features mshv --target=x86_64-unknown-linux-musl
|
||||||
- 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: "1.62"
|
toolchain: "1.67.1"
|
||||||
target: aarch64-unknown-linux-musl
|
target: aarch64-unknown-linux-musl
|
||||||
override: true
|
override: true
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
|||||||
1453
Cargo.lock
generated
1453
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
33
Cargo.toml
33
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "30.0.0"
|
version = "34.0.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "cloud-hypervisor"
|
default-run = "cloud-hypervisor"
|
||||||
@@ -15,7 +15,7 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
|||||||
# a.) A dependency requires it,
|
# a.) A dependency requires it,
|
||||||
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
|
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
|
||||||
# c.) There is a security issue that is addressed by the toolchain update.
|
# c.) There is a security issue that is addressed by the toolchain update.
|
||||||
rust-version = "1.62"
|
rust-version = "1.64"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
@@ -29,43 +29,48 @@ strip = false
|
|||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.71"
|
||||||
api_client = { path = "api_client" }
|
api_client = { path = "api_client" }
|
||||||
argh = "0.1.9"
|
argh = "0.1.9"
|
||||||
dhat = { version = "0.3.2", optional = true }
|
dhat = { version = "0.3.2", optional = true }
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.3"
|
||||||
event_monitor = { path = "event_monitor" }
|
event_monitor = { path = "event_monitor" }
|
||||||
hypervisor = { path = "hypervisor" }
|
hypervisor = { path = "hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = { version = "0.4.17", features = ["std"] }
|
log = { version = "0.4.17", features = ["std"] }
|
||||||
option_parser = { path = "option_parser" }
|
option_parser = { path = "option_parser" }
|
||||||
seccompiler = "0.3.0"
|
seccompiler = "0.3.0"
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.96"
|
||||||
signal-hook = "0.3.14"
|
signal-hook = "0.3.17"
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
tpm = { path = "tpm"}
|
tpm = { path = "tpm"}
|
||||||
tracer = { path = "tracer" }
|
tracer = { path = "tracer" }
|
||||||
vmm = { path = "vmm" }
|
vmm = { path = "vmm" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
vm-memory = "0.10.0"
|
vm-memory = "0.11.0"
|
||||||
|
zbus = { version = "3.11.1", optional = true }
|
||||||
|
|
||||||
# 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.6.0-tdx" }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
|
||||||
|
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
|
||||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
||||||
|
vhost = { git = "https://github.com/rust-vmm/vhost", branch = "main" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dirs = "4.0.0"
|
dirs = "5.0.0"
|
||||||
net_util = { path = "net_util" }
|
net_util = { path = "net_util" }
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.18.0"
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.96"
|
||||||
test_infra = { path = "test_infra" }
|
test_infra = { path = "test_infra" }
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["kvm"]
|
default = ["kvm", "io_uring"]
|
||||||
|
dbus_api = ["zbus", "vmm/dbus_api"]
|
||||||
dhat-heap = ["dhat"] # For heap profiling
|
dhat-heap = ["dhat"] # For heap profiling
|
||||||
guest_debug = ["vmm/guest_debug"]
|
guest_debug = ["vmm/guest_debug"]
|
||||||
|
io_uring = ["vmm/io_uring"]
|
||||||
kvm = ["vmm/kvm"]
|
kvm = ["vmm/kvm"]
|
||||||
mshv = ["vmm/mshv"]
|
mshv = ["vmm/mshv"]
|
||||||
tdx = ["vmm/tdx"]
|
tdx = ["vmm/tdx"]
|
||||||
@@ -75,7 +80,7 @@ tracing = ["vmm/tracing", "tracer/tracing"]
|
|||||||
members = [
|
members = [
|
||||||
"api_client",
|
"api_client",
|
||||||
"arch",
|
"arch",
|
||||||
"block_util",
|
"block",
|
||||||
"devices",
|
"devices",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
"hypervisor",
|
"hypervisor",
|
||||||
@@ -84,12 +89,10 @@ members = [
|
|||||||
"option_parser",
|
"option_parser",
|
||||||
"pci",
|
"pci",
|
||||||
"performance-metrics",
|
"performance-metrics",
|
||||||
"qcow",
|
|
||||||
"rate_limiter",
|
"rate_limiter",
|
||||||
"serial_buffer",
|
"serial_buffer",
|
||||||
"test_infra",
|
"test_infra",
|
||||||
"tracer",
|
"tracer",
|
||||||
"vhdx",
|
|
||||||
"vhost_user_block",
|
"vhost_user_block",
|
||||||
"vhost_user_net",
|
"vhost_user_net",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
|
|||||||
337
Jenkinsfile
vendored
337
Jenkinsfile
vendored
@@ -117,6 +117,63 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage('Worker build - AMD') {
|
||||||
|
agent { node { label 'jammy-amd' } }
|
||||||
|
when {
|
||||||
|
beforeAgent true
|
||||||
|
expression {
|
||||||
|
return runWorkers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Checkout') {
|
||||||
|
steps {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Prepare environment') {
|
||||||
|
steps {
|
||||||
|
sh 'scripts/prepare_vdpa.sh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Run integration tests') {
|
||||||
|
options {
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'sudo modprobe openvswitch'
|
||||||
|
sh 'scripts/dev_cli.sh tests --integration'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Run live-migration integration tests') {
|
||||||
|
options {
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'sudo modprobe openvswitch'
|
||||||
|
sh 'scripts/dev_cli.sh tests --integration-live-migration --integration -- -- --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog_local'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Run integration tests for musl') {
|
||||||
|
options {
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'sudo modprobe openvswitch'
|
||||||
|
sh 'scripts/dev_cli.sh tests --integration --libc musl'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Run live-migration integration tests for musl') {
|
||||||
|
options {
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'sudo modprobe openvswitch'
|
||||||
|
sh 'scripts/dev_cli.sh tests --integration-live-migration --libc musl -- -- --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog --skip live_migration::live_migration_parallel::test_live_upgrade_watchdog_local'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
stage('AArch64 worker build') {
|
stage('AArch64 worker build') {
|
||||||
agent { node { label 'bionic-arm64' } }
|
agent { node { label 'bionic-arm64' } }
|
||||||
when {
|
when {
|
||||||
@@ -238,146 +295,146 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Worker build - Metrics') {
|
// stage('Worker build - Metrics') {
|
||||||
agent { node { label 'jammy-metrics' } }
|
// agent { node { label 'jammy-metrics' } }
|
||||||
when {
|
// when {
|
||||||
branch 'main'
|
// branch 'main'
|
||||||
beforeAgent true
|
// beforeAgent true
|
||||||
expression {
|
// expression {
|
||||||
return runWorkers
|
// return runWorkers
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
environment {
|
// environment {
|
||||||
METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
|
// METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
|
||||||
}
|
// }
|
||||||
stages {
|
// stages {
|
||||||
stage('Checkout') {
|
// stage('Checkout') {
|
||||||
steps {
|
// steps {
|
||||||
checkout scm
|
// checkout scm
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run metrics tests') {
|
// stage('Run metrics tests') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 1, unit: 'HOURS')
|
// timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
|
// sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Upload metrics report') {
|
// stage('Upload metrics report') {
|
||||||
steps {
|
// steps {
|
||||||
sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
|
// sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Worker build - Rate Limiter') {
|
// stage('Worker build - Rate Limiter') {
|
||||||
agent { node { label 'focal-metrics' } }
|
// agent { node { label 'focal-metrics' } }
|
||||||
when {
|
// when {
|
||||||
branch 'main'
|
// branch 'main'
|
||||||
beforeAgent true
|
// beforeAgent true
|
||||||
expression {
|
// expression {
|
||||||
return runWorkers
|
// return runWorkers
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stages {
|
// stages {
|
||||||
stage('Checkout') {
|
// stage('Checkout') {
|
||||||
steps {
|
// steps {
|
||||||
checkout scm
|
// checkout scm
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run rate-limiter integration tests') {
|
// stage('Run rate-limiter integration tests') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 10, unit: 'MINUTES')
|
// timeout(time: 10, unit: 'MINUTES')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
|
// sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Worker build - SGX') {
|
// stage('Worker build - SGX') {
|
||||||
agent { node { label 'jammy-sgx' } }
|
// agent { node { label 'jammy-sgx' } }
|
||||||
when {
|
// when {
|
||||||
beforeAgent true
|
// beforeAgent true
|
||||||
allOf {
|
// allOf {
|
||||||
branch 'main'
|
// branch 'main'
|
||||||
expression {
|
// expression {
|
||||||
return runWorkers
|
// return runWorkers
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stages {
|
// stages {
|
||||||
stage('Checkout') {
|
// stage('Checkout') {
|
||||||
steps {
|
// steps {
|
||||||
checkout scm
|
// checkout scm
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run SGX integration tests') {
|
// stage('Run SGX integration tests') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 1, unit: 'HOURS')
|
// timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --integration-sgx'
|
// sh 'scripts/dev_cli.sh tests --integration-sgx'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run SGX integration tests for musl') {
|
// stage('Run SGX integration tests for musl') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 1, unit: 'HOURS')
|
// timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --integration-sgx --libc musl'
|
// sh 'scripts/dev_cli.sh tests --integration-sgx --libc musl'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
post {
|
// post {
|
||||||
always {
|
// always {
|
||||||
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
// sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
||||||
deleteDir()
|
// deleteDir()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Worker build - VFIO') {
|
// stage('Worker build - VFIO') {
|
||||||
agent { node { label 'jammy-vfio' } }
|
// agent { node { label 'jammy-vfio' } }
|
||||||
when {
|
// when {
|
||||||
beforeAgent true
|
// beforeAgent true
|
||||||
allOf {
|
// allOf {
|
||||||
branch 'main'
|
// branch 'main'
|
||||||
expression {
|
// expression {
|
||||||
return runWorkers
|
// return runWorkers
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stages {
|
// stages {
|
||||||
stage('Checkout') {
|
// stage('Checkout') {
|
||||||
steps {
|
// steps {
|
||||||
checkout scm
|
// checkout scm
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run VFIO integration tests') {
|
// stage('Run VFIO integration tests') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 1, unit: 'HOURS')
|
// timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --integration-vfio'
|
// sh 'scripts/dev_cli.sh tests --integration-vfio'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
stage('Run VFIO integration tests for musl') {
|
// stage('Run VFIO integration tests for musl') {
|
||||||
options {
|
// options {
|
||||||
timeout(time: 1, unit: 'HOURS')
|
// timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
// }
|
||||||
steps {
|
// steps {
|
||||||
sh 'scripts/dev_cli.sh tests --integration-vfio --libc musl'
|
// sh 'scripts/dev_cli.sh tests --integration-vfio --libc musl'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
post {
|
// post {
|
||||||
always {
|
// always {
|
||||||
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
// sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
|
||||||
deleteDir()
|
// deleteDir()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -78,9 +78,9 @@ The following sections describe how to build and run Cloud Hypervisor.
|
|||||||
|
|
||||||
## Host OS
|
## Host OS
|
||||||
|
|
||||||
For required KVM functionality the minimum host kernel version is 4.11. For
|
For required KVM functionality and adequate performance the recommended host
|
||||||
adequate performance the minimum recommended host kernel version is 5.6. The
|
kernel version is 5.13. The majority of the CI currently tests with kernel
|
||||||
majority of the CI currently tests with kernel version 5.15.
|
version 5.15.
|
||||||
|
|
||||||
## Use Pre-built Binaries
|
## Use Pre-built Binaries
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware) or an
|
|||||||
edk2 UEFI firmware called `CLOUDHV` / `CLOUDHV_EFI`.)
|
edk2 UEFI firmware called `CLOUDHV` / `CLOUDHV_EFI`.)
|
||||||
|
|
||||||
Binary builds of the firmware files are available for the latest release of
|
Binary builds of the firmware files are available for the latest release of
|
||||||
[Rust Hyperivor
|
[Rust Hypervisor
|
||||||
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/latest)
|
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/latest)
|
||||||
and [our edk2
|
and [our edk2
|
||||||
repository](https://github.com/cloud-hypervisor/edk2/releases/latest)
|
repository](https://github.com/cloud-hypervisor/edk2/releases/latest)
|
||||||
@@ -124,7 +124,7 @@ may be required.
|
|||||||
### Firmware Booting
|
### Firmware Booting
|
||||||
|
|
||||||
Cloud Hypervisor supports booting disk images containing all needed components
|
Cloud Hypervisor supports booting disk images containing all needed components
|
||||||
to run cloud workloads, a.k.a. cloud images.
|
to run cloud workloads, a.k.a. cloud images.
|
||||||
|
|
||||||
The following sample commands will download an Ubuntu Cloud image, converting
|
The following sample commands will download an Ubuntu Cloud image, converting
|
||||||
it into a format that Cloud Hypervisor can use and a firmware to boot the image
|
it into a format that Cloud Hypervisor can use and a firmware to boot the image
|
||||||
@@ -140,7 +140,10 @@ The Ubuntu cloud images do not ship with a default password so it necessary to
|
|||||||
use a `cloud-init` disk image to customise the image on the first boot. A basic
|
use a `cloud-init` disk image to customise the image on the first boot. A basic
|
||||||
`cloud-init` image is generated by this [script](scripts/create-cloud-init.sh).
|
`cloud-init` image is generated by this [script](scripts/create-cloud-init.sh).
|
||||||
This seeds the image with a default username/password of `cloud/cloud123`. It
|
This seeds the image with a default username/password of `cloud/cloud123`. It
|
||||||
is only necessary to add this disk image on the first boot.
|
is only necessary to add this disk image on the first boot. Script also assigns
|
||||||
|
default IP address using `test_data/cloud-init/ubuntu/local/network-config` details
|
||||||
|
with `--net "mac=12:34:56:78:90:ab,tap="` option. Then the matching mac address
|
||||||
|
interface will be enabled as per `network-config` details.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor
|
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor
|
||||||
@@ -178,7 +181,7 @@ To build the kernel:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Clone the Cloud Hypervisor Linux branch
|
# Clone the Cloud Hypervisor Linux branch
|
||||||
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.1.6 linux-cloud-hypervisor
|
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.2 linux-cloud-hypervisor
|
||||||
$ pushd linux-cloud-hypervisor
|
$ pushd linux-cloud-hypervisor
|
||||||
# Use the x86-64 cloud-hypervisor kernel config to build your kernel for x86-64
|
# Use the x86-64 cloud-hypervisor kernel config to build your kernel for x86-64
|
||||||
$ wget https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/main/resources/linux-config-x86_64
|
$ wget https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/main/resources/linux-config-x86_64
|
||||||
@@ -372,8 +375,8 @@ are all equal and welcome means of contribution. See the
|
|||||||
|
|
||||||
## Slack
|
## Slack
|
||||||
|
|
||||||
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI)
|
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI),
|
||||||
and [join us on Slack](https://cloud-hypervisor.slack.com/).
|
[join us on Slack](https://cloud-hypervisor.slack.com/), and [participate in our community activities](https://cloud-hypervisor.slack.com/archives/C04R5DUQVBN).
|
||||||
|
|
||||||
## Mailing list
|
## Mailing list
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,18 @@ default = []
|
|||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.71"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.9.0", features = ["elf", "bzimage", "pe"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
uuid = "1.3.0"
|
uuid = "1.3.4"
|
||||||
versionize = "0.1.9"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-bitmap"] }
|
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ 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 std::fs;
|
||||||
|
use std::path::Path;
|
||||||
use vm_fdt::{FdtWriter, FdtWriterResult};
|
use vm_fdt::{FdtWriter, FdtWriterResult};
|
||||||
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
||||||
|
|
||||||
@@ -40,8 +42,12 @@ const VIRTIO_IOMMU_PHANDLE: u32 = 5;
|
|||||||
// NOTE: Keep FIRST_VCPU_PHANDLE the last PHANDLE defined.
|
// NOTE: Keep FIRST_VCPU_PHANDLE the last PHANDLE defined.
|
||||||
// This is a value for uniquely identifying the FDT node containing the first vCPU.
|
// This is a value for uniquely identifying the FDT node containing the first vCPU.
|
||||||
// The last number of vCPU phandle depends on the number of vCPUs.
|
// The last number of vCPU phandle depends on the number of vCPUs.
|
||||||
const FIRST_VCPU_PHANDLE: u32 = 6;
|
const FIRST_VCPU_PHANDLE: u32 = 8;
|
||||||
|
|
||||||
|
// This is a value for uniquely identifying the FDT node containing the L2 cache info
|
||||||
|
const L2_CACHE_PHANDLE: u32 = 6;
|
||||||
|
// This is a value for uniquely identifying the FDT node containing the L3 cache info
|
||||||
|
const L3_CACHE_PHANDLE: u32 = 7;
|
||||||
// Read the documentation specified when appending the root node to the FDT.
|
// Read the documentation specified when appending the root node to the FDT.
|
||||||
const ADDRESS_CELLS: u32 = 0x2;
|
const ADDRESS_CELLS: u32 = 0x2;
|
||||||
const SIZE_CELLS: u32 = 0x2;
|
const SIZE_CELLS: u32 = 0x2;
|
||||||
@@ -81,6 +87,97 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
type Result<T> = result::Result<T, Error>;
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
pub enum CacheLevel {
|
||||||
|
/// L1 data cache
|
||||||
|
L1D = 0,
|
||||||
|
/// L1 instruction cache
|
||||||
|
L1I = 1,
|
||||||
|
/// L2 cache
|
||||||
|
L2 = 2,
|
||||||
|
/// L3 cache
|
||||||
|
L3 = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NOTE: CACHE SIZE file directory example,
|
||||||
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/size".
|
||||||
|
pub fn get_cache_size(cache_level: CacheLevel) -> u32 {
|
||||||
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
|
match cache_level {
|
||||||
|
CacheLevel::L1D => file_directory += "/index0/size",
|
||||||
|
CacheLevel::L1I => file_directory += "/index1/size",
|
||||||
|
CacheLevel::L2 => file_directory += "/index2/size",
|
||||||
|
CacheLevel::L3 => file_directory += "/index3/size",
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = Path::new(&file_directory);
|
||||||
|
if !file_path.exists() {
|
||||||
|
error!("File: {} not exist.", file_directory);
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
info!("File: {} exist.", file_directory);
|
||||||
|
|
||||||
|
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
|
||||||
|
// The content of the file is as simple as a size, like: "32K"
|
||||||
|
let src = src.trim();
|
||||||
|
let src_digits: u32 = src[0..src.len() - 1].parse().unwrap();
|
||||||
|
let src_unit = &src[src.len() - 1..];
|
||||||
|
|
||||||
|
src_digits
|
||||||
|
* match src_unit {
|
||||||
|
"K" => 1024,
|
||||||
|
"M" => 1024u32.pow(2),
|
||||||
|
"G" => 1024u32.pow(3),
|
||||||
|
_ => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NOTE: CACHE COHERENCY LINE SIZE file directory example,
|
||||||
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size".
|
||||||
|
pub fn get_cache_coherency_line_size(cache_level: CacheLevel) -> u32 {
|
||||||
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
|
match cache_level {
|
||||||
|
CacheLevel::L1D => file_directory += "/index0/coherency_line_size",
|
||||||
|
CacheLevel::L1I => file_directory += "/index1/coherency_line_size",
|
||||||
|
CacheLevel::L2 => file_directory += "/index2/coherency_line_size",
|
||||||
|
CacheLevel::L3 => file_directory += "/index3/coherency_line_size",
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = Path::new(&file_directory);
|
||||||
|
if !file_path.exists() {
|
||||||
|
error!("File: {} not exist.", file_directory);
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
info!("File: {} exist.", file_directory);
|
||||||
|
|
||||||
|
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
|
||||||
|
src.trim().parse::<u32>().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NOTE: CACHE NUMBER OF SETS file directory example,
|
||||||
|
/// "/sys/devices/system/cpu/cpu0/cache/index0/number_of_sets".
|
||||||
|
pub fn get_cache_number_of_sets(cache_level: CacheLevel) -> u32 {
|
||||||
|
let mut file_directory: String = "/sys/devices/system/cpu/cpu0/cache".to_string();
|
||||||
|
match cache_level {
|
||||||
|
CacheLevel::L1D => file_directory += "/index0/number_of_sets",
|
||||||
|
CacheLevel::L1I => file_directory += "/index1/number_of_sets",
|
||||||
|
CacheLevel::L2 => file_directory += "/index2/number_of_sets",
|
||||||
|
CacheLevel::L3 => file_directory += "/index3/number_of_sets",
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = Path::new(&file_directory);
|
||||||
|
if !file_path.exists() {
|
||||||
|
error!("File: {} not exist.", file_directory);
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
info!("File: {} exist.", file_directory);
|
||||||
|
|
||||||
|
let src = fs::read_to_string(file_directory).expect("File not exists or file corrupted.");
|
||||||
|
src.trim().parse::<u32>().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates the flattened device tree for this aarch64 VM.
|
/// Creates the flattened device tree for this aarch64 VM.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||||
@@ -159,6 +256,54 @@ fn create_cpu_nodes(
|
|||||||
|
|
||||||
let num_cpus = vcpu_mpidr.len();
|
let num_cpus = vcpu_mpidr.len();
|
||||||
|
|
||||||
|
// Add cache info.
|
||||||
|
// L1 Data Cache Info.
|
||||||
|
let mut l1_d_cache_size: u32 = 0;
|
||||||
|
let mut l1_d_cache_line_size: u32 = 0;
|
||||||
|
let mut l1_d_cache_sets: u32 = 0;
|
||||||
|
|
||||||
|
// L1 Instruction Cache Info.
|
||||||
|
let mut l1_i_cache_size: u32 = 0;
|
||||||
|
let mut l1_i_cache_line_size: u32 = 0;
|
||||||
|
let mut l1_i_cache_sets: u32 = 0;
|
||||||
|
|
||||||
|
// L2 Cache Info.
|
||||||
|
let mut l2_cache_size: u32 = 0;
|
||||||
|
let mut l2_cache_line_size: u32 = 0;
|
||||||
|
let mut l2_cache_sets: u32 = 0;
|
||||||
|
|
||||||
|
// L3 Cache Info.
|
||||||
|
let mut l3_cache_size: u32 = 0;
|
||||||
|
let mut l3_cache_line_size: u32 = 0;
|
||||||
|
let mut l3_cache_sets: u32 = 0;
|
||||||
|
|
||||||
|
let cache_path = Path::new("/sys/devices/system/cpu/cpu0/cache");
|
||||||
|
let cache_exist: bool = cache_path.exists();
|
||||||
|
if !cache_exist {
|
||||||
|
error!("cache sysfs system does not exist.");
|
||||||
|
} else {
|
||||||
|
info!("cache sysfs system exists.");
|
||||||
|
// L1 Data Cache Info.
|
||||||
|
l1_d_cache_size = get_cache_size(CacheLevel::L1D);
|
||||||
|
l1_d_cache_line_size = get_cache_coherency_line_size(CacheLevel::L1D);
|
||||||
|
l1_d_cache_sets = get_cache_number_of_sets(CacheLevel::L1D);
|
||||||
|
|
||||||
|
// L1 Instruction Cache Info.
|
||||||
|
l1_i_cache_size = get_cache_size(CacheLevel::L1I);
|
||||||
|
l1_i_cache_line_size = get_cache_coherency_line_size(CacheLevel::L1I);
|
||||||
|
l1_i_cache_sets = get_cache_number_of_sets(CacheLevel::L1I);
|
||||||
|
|
||||||
|
// L2 Cache Info.
|
||||||
|
l2_cache_size = get_cache_size(CacheLevel::L2);
|
||||||
|
l2_cache_line_size = get_cache_coherency_line_size(CacheLevel::L2);
|
||||||
|
l2_cache_sets = get_cache_number_of_sets(CacheLevel::L2);
|
||||||
|
|
||||||
|
// L3 Cache Info.
|
||||||
|
l3_cache_size = get_cache_size(CacheLevel::L3);
|
||||||
|
l3_cache_line_size = get_cache_coherency_line_size(CacheLevel::L3);
|
||||||
|
l3_cache_sets = get_cache_number_of_sets(CacheLevel::L3);
|
||||||
|
}
|
||||||
|
|
||||||
for (cpu_id, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
|
for (cpu_id, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
|
||||||
let cpu_name = format!("cpu@{cpu_id:x}");
|
let cpu_name = format!("cpu@{cpu_id:x}");
|
||||||
let cpu_node = fdt.begin_node(&cpu_name)?;
|
let cpu_node = fdt.begin_node(&cpu_name)?;
|
||||||
@@ -173,6 +318,21 @@ fn create_cpu_nodes(
|
|||||||
fdt.property_u32("reg", (mpidr & 0x7FFFFF) as u32)?;
|
fdt.property_u32("reg", (mpidr & 0x7FFFFF) as u32)?;
|
||||||
fdt.property_u32("phandle", cpu_id as u32 + FIRST_VCPU_PHANDLE)?;
|
fdt.property_u32("phandle", cpu_id as u32 + FIRST_VCPU_PHANDLE)?;
|
||||||
|
|
||||||
|
if cache_exist && l1_d_cache_size != 0 && l1_i_cache_size != 0 {
|
||||||
|
// Add cache info.
|
||||||
|
fdt.property_u32("d-cache-size", l1_d_cache_size)?;
|
||||||
|
fdt.property_u32("d-cache-line-size", l1_d_cache_line_size)?;
|
||||||
|
fdt.property_u32("d-cache-sets", l1_d_cache_sets)?;
|
||||||
|
|
||||||
|
fdt.property_u32("i-cache-size", l1_i_cache_size)?;
|
||||||
|
fdt.property_u32("i-cache-line-size", l1_i_cache_line_size)?;
|
||||||
|
fdt.property_u32("i-cache-sets", l1_i_cache_sets)?;
|
||||||
|
|
||||||
|
if l2_cache_size != 0 {
|
||||||
|
fdt.property_u32("next-level-cache", L2_CACHE_PHANDLE)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add `numa-node-id` property if there is any numa config.
|
// Add `numa-node-id` property if there is any numa config.
|
||||||
if numa_nodes.len() > 1 {
|
if numa_nodes.len() > 1 {
|
||||||
for numa_node_idx in 0..numa_nodes.len() {
|
for numa_node_idx in 0..numa_nodes.len() {
|
||||||
@@ -186,6 +346,36 @@ fn create_cpu_nodes(
|
|||||||
fdt.end_node(cpu_node)?;
|
fdt.end_node(cpu_node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cache_exist && l2_cache_size != 0 {
|
||||||
|
let l2_cache_name = "l2-cache0";
|
||||||
|
let l2_cache_node = fdt.begin_node(l2_cache_name)?;
|
||||||
|
fdt.property_u32("phandle", L2_CACHE_PHANDLE)?;
|
||||||
|
fdt.property_string("compatible", "cache")?;
|
||||||
|
fdt.property_u32("cache-size", l2_cache_size)?;
|
||||||
|
fdt.property_u32("cache-line-size", l2_cache_line_size)?;
|
||||||
|
fdt.property_u32("cache-sets", l2_cache_sets)?;
|
||||||
|
fdt.property_u32("cache-level", 2)?;
|
||||||
|
|
||||||
|
if l3_cache_size != 0 {
|
||||||
|
fdt.property_u32("next-level-cache", L3_CACHE_PHANDLE)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt.end_node(l2_cache_node)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cache_exist && l3_cache_size != 0 {
|
||||||
|
let l3_cache_name = "l3-cache0";
|
||||||
|
let l3_cache_node = fdt.begin_node(l3_cache_name)?;
|
||||||
|
fdt.property_u32("phandle", L3_CACHE_PHANDLE)?;
|
||||||
|
fdt.property_string("compatible", "cache")?;
|
||||||
|
fdt.property_null("cache-unified")?;
|
||||||
|
fdt.property_u32("cache-size", l3_cache_size)?;
|
||||||
|
fdt.property_u32("cache-line-size", l3_cache_line_size)?;
|
||||||
|
fdt.property_u32("cache-sets", l3_cache_sets)?;
|
||||||
|
fdt.property_u32("cache-level", 3)?;
|
||||||
|
fdt.end_node(l3_cache_node)?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(topology) = vcpu_topology {
|
if let Some(topology) = vcpu_topology {
|
||||||
let (threads_per_core, cores_per_package, packages) = topology;
|
let (threads_per_core, cores_per_package, packages) = topology;
|
||||||
let cpu_map_node = fdt.begin_node("cpu-map")?;
|
let cpu_map_node = fdt.begin_node("cpu-map")?;
|
||||||
@@ -260,32 +450,86 @@ fn create_memory_node(
|
|||||||
fdt.end_node(memory_node)?;
|
fdt.end_node(memory_node)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let last_addr = guest_mem.last_addr().raw_value();
|
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
|
||||||
if last_addr < super::layout::MEM_32BIT_RESERVED_START.raw_value() {
|
let ram_regions = {
|
||||||
// Case 1: all RAM is under the hole
|
let mut ram_regions = Vec::new();
|
||||||
let mem_size = last_addr - super::layout::RAM_START.raw_value() + 1;
|
let mut current_start = guest_mem
|
||||||
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
|
.iter()
|
||||||
let memory_node = fdt.begin_node("memory")?;
|
.next()
|
||||||
fdt.property_string("device_type", "memory")?;
|
.map(GuestMemoryRegion::start_addr)
|
||||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
.expect("GuestMemory must have one memory region at least")
|
||||||
fdt.end_node(memory_node)?;
|
.raw_value();
|
||||||
} else {
|
let mut current_end = current_start;
|
||||||
// Case 2: RAM is split by the hole
|
|
||||||
// Region 1: RAM before the hole
|
for (start, size) in guest_mem
|
||||||
let mem_size = super::layout::MEM_32BIT_RESERVED_START.raw_value()
|
.iter()
|
||||||
- super::layout::RAM_START.raw_value();
|
.map(|m| (m.start_addr().raw_value(), m.len()))
|
||||||
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
|
{
|
||||||
let memory_node_name = format!("memory@{:x}", super::layout::RAM_START.raw_value());
|
if current_end == start {
|
||||||
|
// This zone is continuous with the previous one.
|
||||||
|
current_end += size;
|
||||||
|
} else {
|
||||||
|
ram_regions.push((current_start, current_end));
|
||||||
|
|
||||||
|
current_start = start;
|
||||||
|
current_end = start + size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ram_regions.push((current_start, current_end));
|
||||||
|
|
||||||
|
ram_regions
|
||||||
|
};
|
||||||
|
|
||||||
|
if ram_regions.len() > 2 {
|
||||||
|
panic!(
|
||||||
|
"There should be up to two non-continuous regions, devidided by the
|
||||||
|
gap at the end of 32bit address space."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the memory node for memory region before the gap
|
||||||
|
{
|
||||||
|
let (first_region_start, first_region_end) = ram_regions
|
||||||
|
.first()
|
||||||
|
.expect("There should be at last one memory region");
|
||||||
|
let ram_start = super::layout::RAM_START.raw_value();
|
||||||
|
let mem_32bit_reserved_start = super::layout::MEM_32BIT_RESERVED_START.raw_value();
|
||||||
|
|
||||||
|
if !((first_region_start <= &ram_start)
|
||||||
|
&& (first_region_end > &ram_start)
|
||||||
|
&& (first_region_end <= &mem_32bit_reserved_start))
|
||||||
|
{
|
||||||
|
panic!(
|
||||||
|
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
|
||||||
|
ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
|
||||||
|
first_region_start, first_region_end, ram_start, mem_32bit_reserved_start
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mem_size = first_region_end - ram_start;
|
||||||
|
let mem_reg_prop = [ram_start, mem_size];
|
||||||
|
let memory_node_name = format!("memory@{:x}", ram_start);
|
||||||
let memory_node = fdt.begin_node(&memory_node_name)?;
|
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||||
fdt.property_string("device_type", "memory")?;
|
fdt.property_string("device_type", "memory")?;
|
||||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
fdt.end_node(memory_node)?;
|
fdt.end_node(memory_node)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Region 2: RAM after the hole
|
// Create the memory map entry for memory region after the gap if any
|
||||||
let mem_size = last_addr - super::layout::RAM_64BIT_START.raw_value() + 1;
|
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
|
||||||
let mem_reg_prop = [super::layout::RAM_64BIT_START.raw_value(), mem_size];
|
let ram_64bit_start = super::layout::RAM_64BIT_START.raw_value();
|
||||||
let memory_node_name =
|
|
||||||
format!("memory@{:x}", super::layout::RAM_64BIT_START.raw_value());
|
if second_region_start != &ram_64bit_start {
|
||||||
|
panic!(
|
||||||
|
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
|
||||||
|
second_region_start, ram_64bit_start
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mem_size = second_region_end - ram_64bit_start;
|
||||||
|
let mem_reg_prop = [ram_64bit_start, mem_size];
|
||||||
|
let memory_node_name = format!("memory@{:x}", ram_64bit_start);
|
||||||
let memory_node = fdt.begin_node(&memory_node_name)?;
|
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||||
fdt.property_string("device_type", "memory")?;
|
fdt.property_string("device_type", "memory")?;
|
||||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ use std::collections::HashMap;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic, GuestUsize};
|
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
|
||||||
|
|
||||||
|
pub const _NSIG: i32 = 65;
|
||||||
|
|
||||||
/// Errors thrown while configuring aarch64 system.
|
/// Errors thrown while configuring aarch64 system.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -81,8 +83,8 @@ pub fn configure_vcpu(
|
|||||||
Ok(mpidr)
|
Ok(mpidr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||||
let mut regions = vec![
|
vec![
|
||||||
// 0 MiB ~ 256 MiB: UEFI, GIC and legacy devices
|
// 0 MiB ~ 256 MiB: UEFI, GIC and legacy devices
|
||||||
(
|
(
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
@@ -101,39 +103,21 @@ 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,
|
||||||
),
|
),
|
||||||
];
|
// 1GiB ~ 4032 MiB: RAM before the gap
|
||||||
|
(
|
||||||
let ram_32bit_space_size =
|
|
||||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START);
|
|
||||||
|
|
||||||
// RAM space
|
|
||||||
// Case1: guest memory fits before the gap
|
|
||||||
if size <= 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,
|
layout::RAM_START,
|
||||||
ram_32bit_space_size as usize,
|
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize,
|
||||||
RegionType::Ram,
|
RegionType::Ram,
|
||||||
));
|
),
|
||||||
// Other memory is placed after 4GiB
|
// 4GiB ~ inf: RAM after the gap
|
||||||
regions.push((
|
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
|
||||||
layout::RAM_64BIT_START,
|
// Add the 32-bit reserved memory hole as a reserved region
|
||||||
(size - ram_32bit_space_size) as usize,
|
(
|
||||||
RegionType::Ram,
|
layout::MEM_32BIT_RESERVED_START,
|
||||||
));
|
layout::MEM_32BIT_RESERVED_SIZE as usize,
|
||||||
}
|
RegionType::Reserved,
|
||||||
|
),
|
||||||
// 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.
|
||||||
@@ -196,11 +180,8 @@ pub fn initramfs_load_addr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_host_cpu_phys_bits() -> u8 {
|
pub fn get_host_cpu_phys_bits(hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u8 {
|
||||||
// A dummy hypervisor created only for querying the host IPA size and will
|
let host_cpu_phys_bits = hypervisor.get_host_ipa_limit().try_into().unwrap();
|
||||||
// be freed after the query.
|
|
||||||
let hv = hypervisor::new().unwrap();
|
|
||||||
let host_cpu_phys_bits = hv.get_host_ipa_limit().try_into().unwrap();
|
|
||||||
if host_cpu_phys_bits == 0 {
|
if host_cpu_phys_bits == 0 {
|
||||||
// Host kernel does not support `get_host_ipa_limit`,
|
// Host kernel does not support `get_host_ipa_limit`,
|
||||||
// we return the default value 40 here.
|
// we return the default value 40 here.
|
||||||
@@ -215,26 +196,12 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arch_memory_regions_dram_2gb() {
|
fn test_arch_memory_regions_dram() {
|
||||||
let regions = arch_memory_regions((1usize << 31) as u64); //2GB
|
let regions = arch_memory_regions();
|
||||||
assert_eq!(5, regions.len());
|
|
||||||
assert_eq!(layout::RAM_START, regions[3].0);
|
|
||||||
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!(6, regions.len());
|
||||||
assert_eq!(layout::RAM_START, regions[3].0);
|
assert_eq!(layout::RAM_START, regions[3].0);
|
||||||
assert_eq!(ram_32bit_space_size, regions[3].1);
|
|
||||||
assert_eq!(RegionType::Ram, regions[3].2);
|
assert_eq!(RegionType::Ram, regions[3].2);
|
||||||
assert_eq!(RegionType::Reserved, regions[5].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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
///
|
// AArch64 system register encoding:
|
||||||
/// AArch64 system register encoding:
|
// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
|
||||||
/// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
|
//
|
||||||
///
|
// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
|
||||||
/// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
|
// +----------+---+-----+-----+-----+-----+-----+----+
|
||||||
/// +----------+---+-----+-----+-----+-----+-----+----+
|
// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
|
||||||
/// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
|
// +----------+---+-----+-----+-----+-----+-----+----+
|
||||||
/// +----------+---+-----+-----+-----+-----+-----+----+
|
//
|
||||||
///
|
// Notes:
|
||||||
/// Notes:
|
// - L and Rt are reserved as implementation defined fields, ignored.
|
||||||
/// - L and Rt are reserved as implementation defined fields, ignored.
|
|
||||||
///
|
|
||||||
const SYSREG_HEAD: u32 = 0b1101010100u32 << 22;
|
const SYSREG_HEAD: u32 = 0b1101010100u32 << 22;
|
||||||
const SYSREG_OP0_SHIFT: u32 = 19;
|
const SYSREG_OP0_SHIFT: u32 = 19;
|
||||||
const SYSREG_OP0_MASK: u32 = 0b11u32 << 19;
|
const SYSREG_OP0_MASK: u32 = 0b11u32 << 19;
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ pub mod 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, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||||
layout::IRQ_BASE, uefi, EntryPoint,
|
layout::IRQ_BASE, uefi, EntryPoint, _NSIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -92,7 +92,7 @@ pub mod x86_64;
|
|||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
|
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
|
||||||
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||||
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint,
|
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, _NSIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use crate::GuestMemoryMmap;
|
|||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
||||||
use hypervisor::{HypervisorCpuError, HypervisorError};
|
use hypervisor::{CpuVendor, HypervisorCpuError, 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,
|
||||||
@@ -39,7 +39,6 @@ const MTRR_EDX_BIT: u8 = 12; // Hypervisor ecx bit.
|
|||||||
const INVARIANT_TSC_EDX_BIT: u8 = 8; // Invariant TSC bit on 0x8000_0007 EDX
|
const INVARIANT_TSC_EDX_BIT: u8 = 8; // Invariant TSC bit on 0x8000_0007 EDX
|
||||||
|
|
||||||
// KVM feature bits
|
// KVM feature bits
|
||||||
const KVM_FEATURE_ASYNC_PF_INT_BIT: u8 = 14;
|
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
const KVM_FEATURE_CLOCKSOURCE_BIT: u8 = 0;
|
const KVM_FEATURE_CLOCKSOURCE_BIT: u8 = 0;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
@@ -53,6 +52,8 @@ const KVM_FEATURE_ASYNC_PF_VMEXIT_BIT: u8 = 10;
|
|||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
|
const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
|
||||||
|
|
||||||
|
pub const _NSIG: i32 = 65;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
/// Specifies the entry point address where the guest must start
|
/// Specifies the entry point address where the guest must start
|
||||||
/// executing code, as well as which of the supported boot protocols
|
/// executing code, as well as which of the supported boot protocols
|
||||||
@@ -208,7 +209,6 @@ impl From<Error> for super::Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum CpuidReg {
|
pub enum CpuidReg {
|
||||||
EAX,
|
EAX,
|
||||||
@@ -674,14 +674,7 @@ pub fn generate_common_cpuid(
|
|||||||
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);
|
||||||
}
|
}
|
||||||
// Disable KVM_FEATURE_ASYNC_PF_INT
|
|
||||||
// This is required until we find out why the asynchronous page
|
|
||||||
// fault is generating unexpected behavior when using interrupt
|
|
||||||
// mechanism.
|
|
||||||
// TODO: Re-enable KVM_FEATURE_ASYNC_PF_INT (#2277)
|
|
||||||
0x4000_0001 => {
|
0x4000_0001 => {
|
||||||
entry.eax &= !(1 << KVM_FEATURE_ASYNC_PF_INT_BIT);
|
|
||||||
|
|
||||||
// These features are not supported by TDX
|
// These features are not supported by TDX
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
if tdx_enabled {
|
if tdx_enabled {
|
||||||
@@ -774,6 +767,13 @@ 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));
|
||||||
|
|
||||||
|
// Set ApicId in cpuid for each vcpu
|
||||||
|
// SAFETY: get host cpuid when eax=1
|
||||||
|
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx;
|
||||||
|
cpu_ebx &= 0xffffff;
|
||||||
|
cpu_ebx |= (id as u32) << 24;
|
||||||
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
|
||||||
|
|
||||||
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation
|
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation
|
||||||
if !kvm_hyperv {
|
if !kvm_hyperv {
|
||||||
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
|
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
|
||||||
@@ -826,47 +826,29 @@ pub fn configure_vcpu(
|
|||||||
/// These should be used to configure the GuestMemory structure for the platform.
|
/// These should be used to configure the GuestMemory structure for the platform.
|
||||||
/// For x86_64 all addresses are valid from the start of the kernel except a
|
/// For x86_64 all addresses are valid from the start of the kernel except a
|
||||||
/// carve out at the end of 32bit address space.
|
/// carve out at the end of 32bit address space.
|
||||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||||
let reserved_memory_gap_start = layout::MEM_32BIT_RESERVED_START
|
vec![
|
||||||
.checked_add(layout::MEM_32BIT_DEVICES_SIZE)
|
// 0 GiB ~ 3GiB: memory before the gap
|
||||||
.expect("32-bit reserved region is too large");
|
(
|
||||||
|
|
||||||
let requested_memory_size = GuestAddress(size);
|
|
||||||
let mut regions = Vec::new();
|
|
||||||
|
|
||||||
// case1: guest memory fits before the gap
|
|
||||||
if size <= layout::MEM_32BIT_RESERVED_START.raw_value() {
|
|
||||||
regions.push((GuestAddress(0), size as usize, RegionType::Ram));
|
|
||||||
// case2: guest memory extends beyond the gap
|
|
||||||
} else {
|
|
||||||
// push memory before the gap
|
|
||||||
regions.push((
|
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
layout::MEM_32BIT_RESERVED_START.raw_value() as usize,
|
layout::MEM_32BIT_RESERVED_START.raw_value() as usize,
|
||||||
RegionType::Ram,
|
RegionType::Ram,
|
||||||
));
|
),
|
||||||
regions.push((
|
// 4 GiB ~ inf: memory after the gap
|
||||||
layout::RAM_64BIT_START,
|
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
|
||||||
requested_memory_size.unchecked_offset_from(layout::MEM_32BIT_RESERVED_START) as usize,
|
// 3 GiB ~ 3712 MiB: 32-bit device memory hole
|
||||||
RegionType::Ram,
|
(
|
||||||
));
|
layout::MEM_32BIT_RESERVED_START,
|
||||||
}
|
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
||||||
|
RegionType::SubRegion,
|
||||||
// Add the 32-bit device memory hole as a sub region.
|
),
|
||||||
regions.push((
|
// 3712 MiB ~ 3968 MiB: 32-bit reserved memory hole
|
||||||
layout::MEM_32BIT_RESERVED_START,
|
(
|
||||||
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
layout::MEM_32BIT_RESERVED_START.unchecked_add(layout::MEM_32BIT_DEVICES_SIZE),
|
||||||
RegionType::SubRegion,
|
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_SIZE) as usize,
|
||||||
));
|
RegionType::Reserved,
|
||||||
|
),
|
||||||
// Add the 32-bit reserved memory hole as a sub region.
|
]
|
||||||
regions.push((
|
|
||||||
reserved_memory_gap_start,
|
|
||||||
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_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.
|
||||||
@@ -964,30 +946,102 @@ fn configure_pvh(
|
|||||||
// Create the memory map entries.
|
// Create the memory map entries.
|
||||||
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
|
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
|
||||||
|
|
||||||
let mem_end = guest_mem.last_addr();
|
// Merge continuous memory regions into one region.
|
||||||
|
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
|
||||||
|
let ram_regions = {
|
||||||
|
let mut ram_regions = Vec::new();
|
||||||
|
let mut current_start = guest_mem
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.map(GuestMemoryRegion::start_addr)
|
||||||
|
.expect("GuestMemory must have one memory region at least")
|
||||||
|
.raw_value();
|
||||||
|
let mut current_end = current_start;
|
||||||
|
|
||||||
if mem_end < layout::MEM_32BIT_RESERVED_START {
|
for (start, size) in guest_mem
|
||||||
add_memmap_entry(
|
.iter()
|
||||||
&mut memmap,
|
.map(|m| (m.start_addr().raw_value(), m.len()))
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
{
|
||||||
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
|
if current_end == start {
|
||||||
E820_RAM,
|
// This zone is continuous with the previous one.
|
||||||
);
|
current_end += size;
|
||||||
} else {
|
} else {
|
||||||
add_memmap_entry(
|
ram_regions.push((current_start, current_end));
|
||||||
&mut memmap,
|
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
current_start = start;
|
||||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
|
current_end = start + size;
|
||||||
E820_RAM,
|
}
|
||||||
);
|
|
||||||
if mem_end > layout::RAM_64BIT_START {
|
|
||||||
add_memmap_entry(
|
|
||||||
&mut memmap,
|
|
||||||
layout::RAM_64BIT_START.raw_value(),
|
|
||||||
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
|
|
||||||
E820_RAM,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ram_regions.push((current_start, current_end));
|
||||||
|
|
||||||
|
ram_regions
|
||||||
|
};
|
||||||
|
|
||||||
|
if ram_regions.len() > 2 {
|
||||||
|
error!(
|
||||||
|
"There should be up to two non-continuous regions, devidided by the
|
||||||
|
gap at the end of 32bit address space (e.g. between 3G and 4G)."
|
||||||
|
);
|
||||||
|
return Err(super::Error::MemmapTableSetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the memory map entry for memory region before the gap
|
||||||
|
{
|
||||||
|
let (first_region_start, first_region_end) =
|
||||||
|
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
|
||||||
|
let high_ram_start = layout::HIGH_RAM_START.raw_value();
|
||||||
|
let mem_32bit_reserved_start = layout::MEM_32BIT_RESERVED_START.raw_value();
|
||||||
|
|
||||||
|
if !((first_region_start <= &high_ram_start)
|
||||||
|
&& (first_region_end > &high_ram_start)
|
||||||
|
&& (first_region_end <= &mem_32bit_reserved_start))
|
||||||
|
{
|
||||||
|
error!(
|
||||||
|
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
|
||||||
|
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
|
||||||
|
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(super::Error::MemmapTableSetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
|
||||||
|
high_ram_start, first_region_end
|
||||||
|
);
|
||||||
|
|
||||||
|
add_memmap_entry(
|
||||||
|
&mut memmap,
|
||||||
|
high_ram_start,
|
||||||
|
first_region_end - high_ram_start,
|
||||||
|
E820_RAM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the memory map entry for memory region after the gap if any
|
||||||
|
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
|
||||||
|
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
|
||||||
|
|
||||||
|
if second_region_start != &ram_64bit_start {
|
||||||
|
error!(
|
||||||
|
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
|
||||||
|
second_region_start, ram_64bit_start
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(super::Error::MemmapTableSetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
|
||||||
|
ram_64bit_start, second_region_end
|
||||||
|
);
|
||||||
|
add_memmap_entry(
|
||||||
|
&mut memmap,
|
||||||
|
ram_64bit_start,
|
||||||
|
second_region_end - ram_64bit_start,
|
||||||
|
E820_RAM,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_memmap_entry(
|
add_memmap_entry(
|
||||||
@@ -1077,7 +1131,7 @@ pub fn initramfs_load_addr(
|
|||||||
Ok(aligned_addr)
|
Ok(aligned_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_host_cpu_phys_bits() -> u8 {
|
pub fn get_host_cpu_phys_bits(hypervisor: &Arc<dyn hypervisor::Hypervisor>) -> u8 {
|
||||||
// SAFETY: call cpuid with valid leaves
|
// SAFETY: call cpuid with valid leaves
|
||||||
unsafe {
|
unsafe {
|
||||||
let leaf = x86_64::__cpuid(0x8000_0000);
|
let leaf = x86_64::__cpuid(0x8000_0000);
|
||||||
@@ -1086,9 +1140,7 @@ pub fn get_host_cpu_phys_bits() -> u8 {
|
|||||||
// Some physical address bits may become reserved when the feature is enabled.
|
// Some physical address bits may become reserved when the feature is enabled.
|
||||||
// See AMD64 Architecture Programmer's Manual Volume 2, Section 7.10.1
|
// See AMD64 Architecture Programmer's Manual Volume 2, Section 7.10.1
|
||||||
let reduced = if leaf.eax >= 0x8000_001f
|
let reduced = if leaf.eax >= 0x8000_001f
|
||||||
&& leaf.ebx == 0x6874_7541 // Vendor ID: AuthenticAMD
|
&& matches!(hypervisor.get_cpu_vendor(), CpuVendor::AMD)
|
||||||
&& leaf.ecx == 0x444d_4163
|
|
||||||
&& leaf.edx == 0x6974_6e65
|
|
||||||
&& x86_64::__cpuid(0x8000_001f).eax & 0x1 != 0
|
&& x86_64::__cpuid(0x8000_001f).eax & 0x1 != 0
|
||||||
{
|
{
|
||||||
(x86_64::__cpuid(0x8000_001f).ebx >> 6) & 0x3f
|
(x86_64::__cpuid(0x8000_001f).ebx >> 6) & 0x3f
|
||||||
@@ -1223,16 +1275,8 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn regions_lt_4gb() {
|
fn regions_base_addr() {
|
||||||
let regions = arch_memory_regions(1 << 29);
|
let regions = arch_memory_regions();
|
||||||
assert_eq!(3, regions.len());
|
|
||||||
assert_eq!(GuestAddress(0), regions[0].0);
|
|
||||||
assert_eq!(1usize << 29, regions[0].1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn regions_gt_4gb() {
|
|
||||||
let regions = arch_memory_regions((1 << 32) + 0x8000);
|
|
||||||
assert_eq!(4, regions.len());
|
assert_eq!(4, regions.len());
|
||||||
assert_eq!(GuestAddress(0), regions[0].0);
|
assert_eq!(GuestAddress(0), regions[0].0);
|
||||||
assert_eq!(GuestAddress(1 << 32), regions[1].0);
|
assert_eq!(GuestAddress(1 << 32), regions[1].0);
|
||||||
@@ -1256,11 +1300,10 @@ mod tests {
|
|||||||
assert!(config_err.is_err());
|
assert!(config_err.is_err());
|
||||||
|
|
||||||
// Now assigning some memory that falls before the 32bit memory hole.
|
// Now assigning some memory that falls before the 32bit memory hole.
|
||||||
let mem_size = 128 << 20;
|
let arch_mem_regions = arch_memory_regions();
|
||||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
|
||||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| r.2 == RegionType::Ram)
|
.filter(|r| r.2 == RegionType::Ram && r.1 != usize::MAX)
|
||||||
.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();
|
||||||
@@ -1278,48 +1321,18 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
|
||||||
let mem_size = 3328 << 20;
|
|
||||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
|
||||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
|
||||||
.iter()
|
|
||||||
.filter(|r| r.2 == RegionType::Ram)
|
|
||||||
.map(|r| (r.0, r.1))
|
|
||||||
.collect();
|
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
|
||||||
configure_system(
|
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
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 arch_mem_regions = arch_memory_regions();
|
||||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
|
||||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| r.2 == RegionType::Ram)
|
.filter(|r| r.2 == RegionType::Ram)
|
||||||
.map(|r| (r.0, r.1))
|
.map(|r| {
|
||||||
|
if r.1 == usize::MAX {
|
||||||
|
(r.0, 128 << 20)
|
||||||
|
} else {
|
||||||
|
(r.0, r.1)
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
configure_system(
|
||||||
|
|||||||
27
block/Cargo.toml
Normal file
27
block/Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "block"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["The Cloud Hypervisor Authors", "The Chromium OS Authors"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
io_uring = ["dep:io-uring"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.4.3"
|
||||||
|
crc32c = "0.6.3"
|
||||||
|
io-uring = { version = "0.6.0", optional = true }
|
||||||
|
libc = "0.2.139"
|
||||||
|
log = "0.4.17"
|
||||||
|
remain = "0.2.11"
|
||||||
|
smallvec = "1.10.0"
|
||||||
|
thiserror = "1.0.40"
|
||||||
|
uuid = { version = "1.3.4", features = ["v4"] }
|
||||||
|
versionize = "0.1.10"
|
||||||
|
versionize_derive = "0.1.4"
|
||||||
|
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||||
|
virtio-queue = "0.8.0"
|
||||||
|
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
|
vmm-sys-util = "0.11.0"
|
||||||
90
block/src/fixed_vhd.rs
Normal file
90
block/src/fixed_vhd.rs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Copyright © 2021 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
use crate::vhd::VhdFooter;
|
||||||
|
use crate::BlockBackend;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FixedVhd {
|
||||||
|
file: File,
|
||||||
|
size: u64,
|
||||||
|
position: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FixedVhd {
|
||||||
|
pub fn new(mut file: File) -> std::io::Result<Self> {
|
||||||
|
let footer = VhdFooter::new(&mut file)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
file,
|
||||||
|
size: footer.current_size(),
|
||||||
|
position: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for FixedVhd {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.file.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for FixedVhd {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
match self.file.read(buf) {
|
||||||
|
Ok(r) => {
|
||||||
|
self.position = self.position.checked_add(r.try_into().unwrap()).unwrap();
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for FixedVhd {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
|
match self.file.write(buf) {
|
||||||
|
Ok(r) => {
|
||||||
|
self.position = self.position.checked_add(r.try_into().unwrap()).unwrap();
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
self.file.sync_all()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Seek for FixedVhd {
|
||||||
|
fn seek(&mut self, newpos: SeekFrom) -> std::io::Result<u64> {
|
||||||
|
match self.file.seek(newpos) {
|
||||||
|
Ok(pos) => {
|
||||||
|
self.position = pos;
|
||||||
|
Ok(pos)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for FixedVhd {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for FixedVhd {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
file: self.file.try_clone().expect("FixedVhd cloning failed"),
|
||||||
|
size: self.size,
|
||||||
|
position: self.position,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,36 +5,29 @@
|
|||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||||
};
|
};
|
||||||
|
use crate::fixed_vhd::FixedVhd;
|
||||||
use crate::raw_async::RawFileAsync;
|
use crate::raw_async::RawFileAsync;
|
||||||
use crate::vhd::VhdFooter;
|
use crate::BlockBackend;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct FixedVhdDiskAsync {
|
pub struct FixedVhdDiskAsync(FixedVhd);
|
||||||
file: File,
|
|
||||||
size: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FixedVhdDiskAsync {
|
impl FixedVhdDiskAsync {
|
||||||
pub fn new(mut file: File) -> std::io::Result<Self> {
|
pub fn new(file: File) -> std::io::Result<Self> {
|
||||||
let footer = VhdFooter::new(&mut file)?;
|
Ok(Self(FixedVhd::new(file)?))
|
||||||
|
|
||||||
Ok(FixedVhdDiskAsync {
|
|
||||||
file,
|
|
||||||
size: footer.current_size(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskFile for FixedVhdDiskAsync {
|
impl DiskFile for FixedVhdDiskAsync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64> {
|
fn size(&mut self) -> DiskFileResult<u64> {
|
||||||
Ok(self.size)
|
Ok(self.0.size().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||||
Ok(Box::new(
|
Ok(Box::new(
|
||||||
FixedVhdAsync::new(self.file.as_raw_fd(), ring_depth, self.size)
|
FixedVhdAsync::new(self.0.as_raw_fd(), ring_depth, self.0.size().unwrap())
|
||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
.map_err(DiskFileError::NewAsyncIo)?,
|
||||||
) as Box<dyn AsyncIo>)
|
) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
@@ -5,36 +5,29 @@
|
|||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||||
};
|
};
|
||||||
|
use crate::fixed_vhd::FixedVhd;
|
||||||
use crate::raw_sync::RawFileSync;
|
use crate::raw_sync::RawFileSync;
|
||||||
use crate::vhd::VhdFooter;
|
use crate::BlockBackend;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct FixedVhdDiskSync {
|
pub struct FixedVhdDiskSync(FixedVhd);
|
||||||
file: File,
|
|
||||||
size: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FixedVhdDiskSync {
|
impl FixedVhdDiskSync {
|
||||||
pub fn new(mut file: File) -> std::io::Result<Self> {
|
pub fn new(file: File) -> std::io::Result<Self> {
|
||||||
let footer = VhdFooter::new(&mut file)?;
|
Ok(Self(FixedVhd::new(file)?))
|
||||||
|
|
||||||
Ok(FixedVhdDiskSync {
|
|
||||||
file,
|
|
||||||
size: footer.current_size(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskFile for FixedVhdDiskSync {
|
impl DiskFile for FixedVhdDiskSync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64> {
|
fn size(&mut self) -> DiskFileResult<u64> {
|
||||||
Ok(self.size)
|
Ok(self.0.size().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||||
Ok(Box::new(
|
Ok(Box::new(
|
||||||
FixedVhdSync::new(self.file.as_raw_fd(), self.size)
|
FixedVhdSync::new(self.0.as_raw_fd(), self.0.size().unwrap())
|
||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
.map_err(DiskFileError::NewAsyncIo)?,
|
||||||
) as Box<dyn AsyncIo>)
|
) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
@@ -12,21 +12,35 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
pub mod async_io;
|
pub mod async_io;
|
||||||
|
pub mod fixed_vhd;
|
||||||
|
#[cfg(feature = "io_uring")]
|
||||||
|
/// Enabled with the `"io_uring"` feature
|
||||||
pub mod fixed_vhd_async;
|
pub mod fixed_vhd_async;
|
||||||
pub mod fixed_vhd_sync;
|
pub mod fixed_vhd_sync;
|
||||||
|
pub mod qcow;
|
||||||
pub mod qcow_sync;
|
pub mod qcow_sync;
|
||||||
|
#[cfg(feature = "io_uring")]
|
||||||
|
/// Async primitives based on `io-uring`
|
||||||
|
///
|
||||||
|
/// Enabled with the `"io_uring"` feature
|
||||||
pub mod raw_async;
|
pub mod raw_async;
|
||||||
pub mod raw_sync;
|
pub mod raw_sync;
|
||||||
pub mod vhd;
|
pub mod vhd;
|
||||||
|
pub mod vhdx;
|
||||||
pub mod vhdx_sync;
|
pub mod vhdx_sync;
|
||||||
|
|
||||||
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
||||||
|
use crate::fixed_vhd::FixedVhd;
|
||||||
|
use crate::qcow::{QcowFile, RawFile};
|
||||||
|
use crate::vhdx::{Vhdx, VhdxError};
|
||||||
|
#[cfg(feature = "io_uring")]
|
||||||
use io_uring::{opcode, IoUring, Probe};
|
use io_uring::{opcode, IoUring, Probe};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||||
use std::os::linux::fs::MetadataExt;
|
use std::os::linux::fs::MetadataExt;
|
||||||
@@ -66,12 +80,22 @@ pub enum Error {
|
|||||||
DescriptorChainTooShort,
|
DescriptorChainTooShort,
|
||||||
#[error("Guest gave us a descriptor that was too short to use")]
|
#[error("Guest gave us a descriptor that was too short to use")]
|
||||||
DescriptorLengthTooSmall,
|
DescriptorLengthTooSmall,
|
||||||
|
#[error("Failed to detect image type: {0}")]
|
||||||
|
DetectImageType(std::io::Error),
|
||||||
|
#[error("Failure in fixed vhd: {0}")]
|
||||||
|
FixedVhdError(std::io::Error),
|
||||||
#[error("Getting a block's metadata fails for any reason")]
|
#[error("Getting a block's metadata fails for any reason")]
|
||||||
GetFileMetadata,
|
GetFileMetadata,
|
||||||
#[error("The requested operation would cause a seek beyond disk end")]
|
#[error("The requested operation would cause a seek beyond disk end")]
|
||||||
InvalidOffset,
|
InvalidOffset,
|
||||||
|
#[error("Failure in qcow: {0}")]
|
||||||
|
QcowError(qcow::Error),
|
||||||
|
#[error("Failure in raw file: {0}")]
|
||||||
|
RawFileError(std::io::Error),
|
||||||
#[error("The requested operation does not support multiple descriptors")]
|
#[error("The requested operation does not support multiple descriptors")]
|
||||||
TooManyDescriptors,
|
TooManyDescriptors,
|
||||||
|
#[error("Failure in vhdx: {0}")]
|
||||||
|
VhdxError(VhdxError),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
||||||
@@ -543,50 +567,59 @@ unsafe impl ByteValued for VirtioBlockGeometry {}
|
|||||||
/// Check if io_uring for block device can be used on the current system, as
|
/// Check if io_uring for block device can be used on the current system, as
|
||||||
/// it correctly supports the expected io_uring features.
|
/// it correctly supports the expected io_uring features.
|
||||||
pub fn block_io_uring_is_supported() -> bool {
|
pub fn block_io_uring_is_supported() -> bool {
|
||||||
let error_msg = "io_uring not supported:";
|
#[cfg(not(feature = "io_uring"))]
|
||||||
|
{
|
||||||
|
info!("io_uring is disabled by crate features");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// Check we can create an io_uring instance, which effectively verifies
|
#[cfg(feature = "io_uring")]
|
||||||
// that io_uring_setup() syscall is supported.
|
{
|
||||||
let io_uring = match IoUring::new(1) {
|
let error_msg = "io_uring not supported:";
|
||||||
Ok(io_uring) => io_uring,
|
|
||||||
Err(e) => {
|
// Check we can create an io_uring instance, which effectively verifies
|
||||||
info!("{} failed to create io_uring instance: {}", error_msg, e);
|
// that io_uring_setup() syscall is supported.
|
||||||
|
let io_uring = match IoUring::new(1) {
|
||||||
|
Ok(io_uring) => io_uring,
|
||||||
|
Err(e) => {
|
||||||
|
info!("{} failed to create io_uring instance: {}", error_msg, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let submitter = io_uring.submitter();
|
||||||
|
|
||||||
|
let mut probe = Probe::new();
|
||||||
|
|
||||||
|
// Check we can register a probe to validate supported operations.
|
||||||
|
match submitter.register_probe(&mut probe) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
info!("{} failed to register a probe: {}", error_msg, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check IORING_OP_FSYNC is supported
|
||||||
|
if !probe.is_supported(opcode::Fsync::CODE) {
|
||||||
|
info!("{} IORING_OP_FSYNC operation not supported", error_msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let submitter = io_uring.submitter();
|
// Check IORING_OP_READV is supported
|
||||||
|
if !probe.is_supported(opcode::Readv::CODE) {
|
||||||
let mut probe = Probe::new();
|
info!("{} IORING_OP_READV operation not supported", error_msg);
|
||||||
|
|
||||||
// Check we can register a probe to validate supported operations.
|
|
||||||
match submitter.register_probe(&mut probe) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
info!("{} failed to register a probe: {}", error_msg, e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check IORING_OP_FSYNC is supported
|
// Check IORING_OP_WRITEV is supported
|
||||||
if !probe.is_supported(opcode::Fsync::CODE) {
|
if !probe.is_supported(opcode::Writev::CODE) {
|
||||||
info!("{} IORING_OP_FSYNC operation not supported", error_msg);
|
info!("{} IORING_OP_WRITEV operation not supported", error_msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check IORING_OP_READV is supported
|
true
|
||||||
if !probe.is_supported(opcode::Readv::CODE) {
|
|
||||||
info!("{} IORING_OP_READV operation not supported", error_msg);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check IORING_OP_WRITEV is supported
|
|
||||||
if !probe.is_supported(opcode::Writev::CODE) {
|
|
||||||
info!("{} IORING_OP_WRITEV operation not supported", error_msg);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsyncAdaptor<F>
|
pub trait AsyncAdaptor<F>
|
||||||
@@ -720,3 +753,26 @@ pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
|
|||||||
|
|
||||||
Ok(image_type)
|
Ok(image_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait BlockBackend: Read + Write + Seek + Send + Debug {
|
||||||
|
fn size(&self) -> Result<u64, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect the image file type and create an appropriate disk file to match it.
|
||||||
|
pub fn create_disk_file(mut file: File, direct_io: bool) -> Result<Box<dyn BlockBackend>, Error> {
|
||||||
|
let image_type = detect_image_type(&mut file).map_err(Error::DetectImageType)?;
|
||||||
|
|
||||||
|
Ok(match image_type {
|
||||||
|
ImageType::Qcow2 => {
|
||||||
|
Box::new(QcowFile::from(RawFile::new(file, direct_io)).map_err(Error::QcowError)?)
|
||||||
|
as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::FixedVhd => {
|
||||||
|
Box::new(FixedVhd::new(file).map_err(Error::FixedVhdError)?) as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::Vhdx => {
|
||||||
|
Box::new(Vhdx::new(file).map_err(Error::VhdxError)?) as Box<dyn BlockBackend>
|
||||||
|
}
|
||||||
|
ImageType::Raw => Box::new(RawFile::new(file, direct_io)) as Box<dyn BlockBackend>,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -2,40 +2,45 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
mod qcow_raw_file;
|
mod qcow_raw_file;
|
||||||
mod raw_file;
|
mod raw_file;
|
||||||
mod refcount;
|
mod refcount;
|
||||||
mod vec_cache;
|
mod vec_cache;
|
||||||
|
|
||||||
use crate::qcow_raw_file::QcowRawFile;
|
use crate::qcow::{
|
||||||
use crate::refcount::RefCount;
|
qcow_raw_file::QcowRawFile,
|
||||||
use crate::vec_cache::{CacheMap, Cacheable, VecCache};
|
refcount::RefCount,
|
||||||
|
vec_cache::{CacheMap, Cacheable, VecCache},
|
||||||
|
};
|
||||||
|
use crate::BlockBackend;
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use libc::{EINVAL, ENOSPC, ENOTSUP};
|
use libc::{EINVAL, ENOSPC, ENOTSUP};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
use std::fs::OpenOptions;
|
||||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
use std::str;
|
||||||
use vmm_sys_util::{
|
use vmm_sys_util::{
|
||||||
file_traits::FileSetLen, file_traits::FileSync, seek_hole::SeekHole, write_zeroes::PunchHole,
|
file_traits::FileSetLen, file_traits::FileSync, seek_hole::SeekHole, write_zeroes::PunchHole,
|
||||||
write_zeroes::WriteZeroesAt,
|
write_zeroes::WriteZeroesAt,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::raw_file::RawFile;
|
pub use crate::qcow::raw_file::RawFile;
|
||||||
|
|
||||||
#[sorted]
|
#[sorted]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
BackingFilesNotSupported,
|
BackingFileIo(io::Error),
|
||||||
|
BackingFileOpen(Box<crate::Error>),
|
||||||
|
BackingFileTooLong(usize),
|
||||||
CompressedBlocksNotSupported,
|
CompressedBlocksNotSupported,
|
||||||
EvictingCache(io::Error),
|
EvictingCache(io::Error),
|
||||||
FileTooBig(u64),
|
FileTooBig(u64),
|
||||||
GettingFileSize(io::Error),
|
GettingFileSize(io::Error),
|
||||||
GettingRefcount(refcount::Error),
|
GettingRefcount(refcount::Error),
|
||||||
|
InvalidBackingFileName(str::Utf8Error),
|
||||||
InvalidClusterIndex,
|
InvalidClusterIndex,
|
||||||
InvalidClusterSize,
|
InvalidClusterSize,
|
||||||
InvalidIndex,
|
InvalidIndex,
|
||||||
@@ -78,12 +83,17 @@ impl Display for Error {
|
|||||||
|
|
||||||
#[sorted]
|
#[sorted]
|
||||||
match self {
|
match self {
|
||||||
BackingFilesNotSupported => write!(f, "backing files not supported"),
|
BackingFileIo(e) => write!(f, "backing file io error: {}", e),
|
||||||
|
BackingFileOpen(e) => write!(f, "backing file open error: {}", *e),
|
||||||
|
BackingFileTooLong(len) => {
|
||||||
|
write!(f, "backing file name is too long: {} bytes over", len)
|
||||||
|
}
|
||||||
CompressedBlocksNotSupported => write!(f, "compressed blocks not supported"),
|
CompressedBlocksNotSupported => write!(f, "compressed blocks not supported"),
|
||||||
EvictingCache(e) => write!(f, "failed to evict cache: {e}"),
|
EvictingCache(e) => write!(f, "failed to evict cache: {e}"),
|
||||||
FileTooBig(size) => write!(f, "file larger than max of {MAX_QCOW_FILE_SIZE}: {size}"),
|
FileTooBig(size) => write!(f, "file larger than max of {MAX_QCOW_FILE_SIZE}: {size}"),
|
||||||
GettingFileSize(e) => write!(f, "failed to get file size: {e}"),
|
GettingFileSize(e) => write!(f, "failed to get file size: {e}"),
|
||||||
GettingRefcount(e) => write!(f, "failed to get refcount: {e}"),
|
GettingRefcount(e) => write!(f, "failed to get refcount: {e}"),
|
||||||
|
InvalidBackingFileName(e) => write!(f, "failed to parse filename: {}", e),
|
||||||
InvalidClusterIndex => write!(f, "invalid cluster index"),
|
InvalidClusterIndex => write!(f, "invalid cluster index"),
|
||||||
InvalidClusterSize => write!(f, "invalid cluster size"),
|
InvalidClusterSize => write!(f, "invalid cluster size"),
|
||||||
InvalidIndex => write!(f, "invalid index"),
|
InvalidIndex => write!(f, "invalid index"),
|
||||||
@@ -153,8 +163,14 @@ const COMPRESSED_FLAG: u64 = 1 << 62;
|
|||||||
const CLUSTER_USED_FLAG: u64 = 1 << 63;
|
const CLUSTER_USED_FLAG: u64 = 1 << 63;
|
||||||
const COMPATIBLE_FEATURES_LAZY_REFCOUNTS: u64 = 1;
|
const COMPATIBLE_FEATURES_LAZY_REFCOUNTS: u64 = 1;
|
||||||
|
|
||||||
|
// The format supports a "header extension area", that crosvm does not use.
|
||||||
|
const QCOW_EMPTY_HEADER_EXTENSION_SIZE: u32 = 8;
|
||||||
|
|
||||||
|
// Defined by the specification
|
||||||
|
const MAX_BACKING_FILE_SIZE: u32 = 1023;
|
||||||
|
|
||||||
/// Contains the information from the header of a qcow file.
|
/// Contains the information from the header of a qcow file.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct QcowHeader {
|
pub struct QcowHeader {
|
||||||
pub magic: u32,
|
pub magic: u32,
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
@@ -181,6 +197,9 @@ pub struct QcowHeader {
|
|||||||
pub autoclear_features: u64,
|
pub autoclear_features: u64,
|
||||||
pub refcount_order: u32,
|
pub refcount_order: u32,
|
||||||
pub header_size: u32,
|
pub header_size: u32,
|
||||||
|
|
||||||
|
// Post-header entries
|
||||||
|
pub backing_file_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QcowHeader {
|
impl QcowHeader {
|
||||||
@@ -204,7 +223,7 @@ impl QcowHeader {
|
|||||||
|
|
||||||
let version = read_u32_from_file(f)?;
|
let version = read_u32_from_file(f)?;
|
||||||
|
|
||||||
Ok(QcowHeader {
|
let mut header = QcowHeader {
|
||||||
magic,
|
magic,
|
||||||
version,
|
version,
|
||||||
backing_file_offset: read_u64_from_file(f)?,
|
backing_file_offset: read_u64_from_file(f)?,
|
||||||
@@ -243,24 +262,58 @@ impl QcowHeader {
|
|||||||
} else {
|
} else {
|
||||||
read_u32_from_file(f)?
|
read_u32_from_file(f)?
|
||||||
},
|
},
|
||||||
})
|
backing_file_path: None,
|
||||||
|
};
|
||||||
|
if header.backing_file_size > MAX_BACKING_FILE_SIZE {
|
||||||
|
return Err(Error::BackingFileTooLong(header.backing_file_size as usize));
|
||||||
|
}
|
||||||
|
if header.backing_file_offset != 0 {
|
||||||
|
f.seek(SeekFrom::Start(header.backing_file_offset))
|
||||||
|
.map_err(Error::ReadingHeader)?;
|
||||||
|
let mut backing_file_name_bytes = vec![0u8; header.backing_file_size as usize];
|
||||||
|
f.read_exact(&mut backing_file_name_bytes)
|
||||||
|
.map_err(Error::ReadingHeader)?;
|
||||||
|
header.backing_file_path = Some(
|
||||||
|
String::from_utf8(backing_file_name_bytes)
|
||||||
|
.map_err(|err| Error::InvalidBackingFileName(err.utf8_error()))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(header)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a header for the given `size`.
|
pub fn create_for_size_and_path(
|
||||||
pub fn create_for_size(version: u32, size: u64) -> QcowHeader {
|
version: u32,
|
||||||
|
size: u64,
|
||||||
|
backing_file: Option<&str>,
|
||||||
|
) -> Result<QcowHeader> {
|
||||||
|
let header_size = if version == 2 {
|
||||||
|
V2_BARE_HEADER_SIZE
|
||||||
|
} else {
|
||||||
|
V3_BARE_HEADER_SIZE + QCOW_EMPTY_HEADER_EXTENSION_SIZE
|
||||||
|
};
|
||||||
let cluster_bits: u32 = DEFAULT_CLUSTER_BITS;
|
let cluster_bits: u32 = DEFAULT_CLUSTER_BITS;
|
||||||
let cluster_size: u32 = 0x01 << cluster_bits;
|
let cluster_size: u32 = 0x01 << cluster_bits;
|
||||||
|
let max_length: usize = (cluster_size - header_size) as usize;
|
||||||
|
if let Some(path) = backing_file {
|
||||||
|
if path.len() > max_length {
|
||||||
|
return Err(Error::BackingFileTooLong(path.len() - max_length));
|
||||||
|
}
|
||||||
|
}
|
||||||
// L2 blocks are always one cluster long. They contain cluster_size/sizeof(u64) addresses.
|
// L2 blocks are always one cluster long. They contain cluster_size/sizeof(u64) addresses.
|
||||||
let entries_per_cluster: u32 = cluster_size / size_of::<u64>() as u32;
|
let entries_per_cluster: u32 = cluster_size / size_of::<u64>() as u32;
|
||||||
let num_clusters: u32 = div_round_up_u64(size, u64::from(cluster_size)) as u32;
|
let num_clusters: u32 = div_round_up_u64(size, u64::from(cluster_size)) as u32;
|
||||||
let num_l2_clusters: u32 = div_round_up_u32(num_clusters, entries_per_cluster);
|
let num_l2_clusters: u32 = div_round_up_u32(num_clusters, entries_per_cluster);
|
||||||
let l1_clusters: u32 = div_round_up_u32(num_l2_clusters, entries_per_cluster);
|
let l1_clusters: u32 = div_round_up_u32(num_l2_clusters, entries_per_cluster);
|
||||||
let header_clusters = div_round_up_u32(size_of::<QcowHeader>() as u32, cluster_size);
|
let header_clusters = div_round_up_u32(size_of::<QcowHeader>() as u32, cluster_size);
|
||||||
QcowHeader {
|
Ok(QcowHeader {
|
||||||
magic: QCOW_MAGIC,
|
magic: QCOW_MAGIC,
|
||||||
version,
|
version,
|
||||||
backing_file_offset: 0,
|
backing_file_offset: (if backing_file.is_none() {
|
||||||
backing_file_size: 0,
|
0
|
||||||
|
} else {
|
||||||
|
header_size
|
||||||
|
}) as u64,
|
||||||
|
backing_file_size: backing_file.map_or(0, |x| x.len()) as u32,
|
||||||
cluster_bits: DEFAULT_CLUSTER_BITS,
|
cluster_bits: DEFAULT_CLUSTER_BITS,
|
||||||
size,
|
size,
|
||||||
crypt_method: 0,
|
crypt_method: 0,
|
||||||
@@ -289,12 +342,9 @@ impl QcowHeader {
|
|||||||
compatible_features: 0,
|
compatible_features: 0,
|
||||||
autoclear_features: 0,
|
autoclear_features: 0,
|
||||||
refcount_order: DEFAULT_REFCOUNT_ORDER,
|
refcount_order: DEFAULT_REFCOUNT_ORDER,
|
||||||
header_size: if version == 2 {
|
header_size,
|
||||||
V2_BARE_HEADER_SIZE
|
backing_file_path: backing_file.map(String::from),
|
||||||
} else {
|
})
|
||||||
V3_BARE_HEADER_SIZE
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the header to `file`.
|
/// Write the header to `file`.
|
||||||
@@ -324,11 +374,20 @@ impl QcowHeader {
|
|||||||
write_u32_to_file(file, self.refcount_table_clusters)?;
|
write_u32_to_file(file, self.refcount_table_clusters)?;
|
||||||
write_u32_to_file(file, self.nb_snapshots)?;
|
write_u32_to_file(file, self.nb_snapshots)?;
|
||||||
write_u64_to_file(file, self.snapshots_offset)?;
|
write_u64_to_file(file, self.snapshots_offset)?;
|
||||||
write_u64_to_file(file, self.incompatible_features)?;
|
|
||||||
write_u64_to_file(file, self.compatible_features)?;
|
if self.version == 3 {
|
||||||
write_u64_to_file(file, self.autoclear_features)?;
|
write_u64_to_file(file, self.incompatible_features)?;
|
||||||
write_u32_to_file(file, self.refcount_order)?;
|
write_u64_to_file(file, self.compatible_features)?;
|
||||||
write_u32_to_file(file, self.header_size)?;
|
write_u64_to_file(file, self.autoclear_features)?;
|
||||||
|
write_u32_to_file(file, self.refcount_order)?;
|
||||||
|
write_u32_to_file(file, self.header_size)?;
|
||||||
|
write_u32_to_file(file, 0)?; // header extension type: end of header extension area
|
||||||
|
write_u32_to_file(file, 0)?; // length of header extension data: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(backing_file_path) = self.backing_file_path.as_ref() {
|
||||||
|
write!(file, "{}", backing_file_path).map_err(Error::WritingHeader)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the file length by seeking and writing a zero to the last byte. This avoids needing
|
// Set the file length by seeking and writing a zero to the last byte. This avoids needing
|
||||||
// a `File` instead of anything that implements seek as the `file` argument.
|
// a `File` instead of anything that implements seek as the `file` argument.
|
||||||
@@ -362,8 +421,8 @@ fn max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
/// # use block::qcow::{self, QcowFile, RawFile};
|
||||||
/// # use std::io::{Read, Seek, SeekFrom};
|
/// # use std::io::{Read, Seek, SeekFrom};
|
||||||
/// # use qcow::{self, QcowFile, RawFile};
|
|
||||||
/// # fn test(file: std::fs::File) -> std::io::Result<()> {
|
/// # fn test(file: std::fs::File) -> std::io::Result<()> {
|
||||||
/// let mut raw_img = RawFile::new(file, false);
|
/// let mut raw_img = RawFile::new(file, false);
|
||||||
/// let mut q = QcowFile::from(raw_img).expect("Can't open qcow file");
|
/// let mut q = QcowFile::from(raw_img).expect("Can't open qcow file");
|
||||||
@@ -373,7 +432,7 @@ fn max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QcowFile {
|
pub struct QcowFile {
|
||||||
raw_file: QcowRawFile,
|
raw_file: QcowRawFile,
|
||||||
header: QcowHeader,
|
header: QcowHeader,
|
||||||
@@ -386,7 +445,7 @@ pub struct QcowFile {
|
|||||||
// List of unreferenced clusters available to be used. unref clusters become available once the
|
// List of unreferenced clusters available to be used. unref clusters become available once the
|
||||||
// removal of references to them have been synced to disk.
|
// removal of references to them have been synced to disk.
|
||||||
avail_clusters: Vec<u64>,
|
avail_clusters: Vec<u64>,
|
||||||
//TODO(dgreid) Add support for backing files. - backing_file: Option<Box<QcowFile<T>>>,
|
backing_file: Option<Box<dyn BlockBackend>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QcowFile {
|
impl QcowFile {
|
||||||
@@ -415,10 +474,20 @@ impl QcowFile {
|
|||||||
return Err(Error::FileTooBig(header.size));
|
return Err(Error::FileTooBig(header.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No current support for backing files.
|
let direct_io = file.is_direct();
|
||||||
if header.backing_file_offset != 0 {
|
|
||||||
return Err(Error::BackingFilesNotSupported);
|
let backing_file = if let Some(backing_file_path) = header.backing_file_path.as_ref() {
|
||||||
}
|
let path = backing_file_path.clone();
|
||||||
|
let backing_raw_file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(path)
|
||||||
|
.map_err(Error::BackingFileIo)?;
|
||||||
|
let backing_file = crate::create_disk_file(backing_raw_file, direct_io)
|
||||||
|
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
|
||||||
|
Some(backing_file)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Only support two byte refcounts.
|
// Only support two byte refcounts.
|
||||||
let refcount_bits: u64 = 0x01u64
|
let refcount_bits: u64 = 0x01u64
|
||||||
@@ -433,7 +502,6 @@ impl QcowFile {
|
|||||||
if header.refcount_table_clusters == 0 {
|
if header.refcount_table_clusters == 0 {
|
||||||
return Err(Error::NoRefcountClusters);
|
return Err(Error::NoRefcountClusters);
|
||||||
}
|
}
|
||||||
offset_is_cluster_boundary(header.backing_file_offset, header.cluster_bits)?;
|
|
||||||
offset_is_cluster_boundary(header.l1_table_offset, header.cluster_bits)?;
|
offset_is_cluster_boundary(header.l1_table_offset, header.cluster_bits)?;
|
||||||
offset_is_cluster_boundary(header.snapshots_offset, header.cluster_bits)?;
|
offset_is_cluster_boundary(header.snapshots_offset, header.cluster_bits)?;
|
||||||
// refcount table must be a cluster boundary, and within the file's virtual or actual size.
|
// refcount table must be a cluster boundary, and within the file's virtual or actual size.
|
||||||
@@ -466,7 +534,7 @@ impl QcowFile {
|
|||||||
let mut raw_file =
|
let mut raw_file =
|
||||||
QcowRawFile::from(file, cluster_size).ok_or(Error::InvalidClusterSize)?;
|
QcowRawFile::from(file, cluster_size).ok_or(Error::InvalidClusterSize)?;
|
||||||
if refcount_rebuild_required {
|
if refcount_rebuild_required {
|
||||||
QcowFile::rebuild_refcounts(&mut raw_file, header)?;
|
QcowFile::rebuild_refcounts(&mut raw_file, header.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries_per_cluster = cluster_size / size_of::<u64>() as u64;
|
let entries_per_cluster = cluster_size / size_of::<u64>() as u64;
|
||||||
@@ -535,6 +603,7 @@ impl QcowFile {
|
|||||||
current_offset: 0,
|
current_offset: 0,
|
||||||
unref_clusters: Vec::new(),
|
unref_clusters: Vec::new(),
|
||||||
avail_clusters: Vec::new(),
|
avail_clusters: Vec::new(),
|
||||||
|
backing_file,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that the L1 and refcount tables fit in a 64bit address space.
|
// Check that the L1 and refcount tables fit in a 64bit address space.
|
||||||
@@ -553,8 +622,34 @@ impl QcowFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new QcowFile at the given path.
|
/// Creates a new QcowFile at the given path.
|
||||||
pub fn new(mut file: RawFile, version: u32, virtual_size: u64) -> Result<QcowFile> {
|
pub fn new(file: RawFile, version: u32, virtual_size: u64) -> Result<QcowFile> {
|
||||||
let header = QcowHeader::create_for_size(version, virtual_size);
|
let header = QcowHeader::create_for_size_and_path(version, virtual_size, None)?;
|
||||||
|
QcowFile::new_from_header(file, header)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new QcowFile at the given path.
|
||||||
|
pub fn new_from_backing(
|
||||||
|
file: RawFile,
|
||||||
|
version: u32,
|
||||||
|
backing_file_name: &str,
|
||||||
|
) -> Result<QcowFile> {
|
||||||
|
let direct_io = file.is_direct();
|
||||||
|
let backing_raw_file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(backing_file_name)
|
||||||
|
.map_err(Error::BackingFileIo)?;
|
||||||
|
let backing_file = crate::create_disk_file(backing_raw_file, direct_io)
|
||||||
|
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
|
||||||
|
let size = backing_file
|
||||||
|
.size()
|
||||||
|
.map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
|
||||||
|
let header = QcowHeader::create_for_size_and_path(version, size, Some(backing_file_name))?;
|
||||||
|
let mut result = QcowFile::new_from_header(file, header)?;
|
||||||
|
result.backing_file = Some(backing_file);
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_from_header(mut file: RawFile, header: QcowHeader) -> Result<QcowFile> {
|
||||||
file.rewind().map_err(Error::SeekingFile)?;
|
file.rewind().map_err(Error::SeekingFile)?;
|
||||||
header.write_to(&mut file)?;
|
header.write_to(&mut file)?;
|
||||||
|
|
||||||
@@ -578,6 +673,10 @@ impl QcowFile {
|
|||||||
Ok(qcow)
|
Ok(qcow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_backing_file(&mut self, backing: Option<Box<dyn BlockBackend>>) {
|
||||||
|
self.backing_file = backing;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the `QcowHeader` for this file.
|
/// Returns the `QcowHeader` for this file.
|
||||||
pub fn header(&self) -> &QcowHeader {
|
pub fn header(&self) -> &QcowHeader {
|
||||||
&self.header
|
&self.header
|
||||||
@@ -890,9 +989,9 @@ impl QcowFile {
|
|||||||
|
|
||||||
// Find all references clusters and rebuild refcounts.
|
// Find all references clusters and rebuild refcounts.
|
||||||
set_header_refcount(&mut refcounts, cluster_size)?;
|
set_header_refcount(&mut refcounts, cluster_size)?;
|
||||||
set_l1_refcounts(&mut refcounts, header, cluster_size)?;
|
set_l1_refcounts(&mut refcounts, header.clone(), cluster_size)?;
|
||||||
set_data_refcounts(&mut refcounts, header, cluster_size, raw_file)?;
|
set_data_refcounts(&mut refcounts, header.clone(), cluster_size, raw_file)?;
|
||||||
set_refcount_table_refcounts(&mut refcounts, header, cluster_size)?;
|
set_refcount_table_refcounts(&mut refcounts, header.clone(), cluster_size)?;
|
||||||
|
|
||||||
// Allocate clusters to store the new reference count blocks.
|
// Allocate clusters to store the new reference count blocks.
|
||||||
let ref_table = alloc_refblocks(&mut refcounts, cluster_size, refblock_clusters)?;
|
let ref_table = alloc_refblocks(&mut refcounts, cluster_size, refblock_clusters)?;
|
||||||
@@ -1007,7 +1106,7 @@ impl QcowFile {
|
|||||||
let l2_table = if l2_addr_disk == 0 {
|
let l2_table = if l2_addr_disk == 0 {
|
||||||
// Allocate a new cluster to store the L2 table and update the L1 table to point
|
// Allocate a new cluster to store the L2 table and update the L1 table to point
|
||||||
// to the new table.
|
// to the new table.
|
||||||
let new_addr: u64 = self.get_new_cluster()?;
|
let new_addr: u64 = self.get_new_cluster(None)?;
|
||||||
// The cluster refcount starts at one meaning it is used but doesn't need COW.
|
// The cluster refcount starts at one meaning it is used but doesn't need COW.
|
||||||
set_refcounts.push((new_addr, 1));
|
set_refcounts.push((new_addr, 1));
|
||||||
self.l1_table[l1_index] = new_addr;
|
self.l1_table[l1_index] = new_addr;
|
||||||
@@ -1028,8 +1127,18 @@ impl QcowFile {
|
|||||||
|
|
||||||
let cluster_addr = match self.l2_cache.get(l1_index).unwrap()[l2_index] {
|
let cluster_addr = match self.l2_cache.get(l1_index).unwrap()[l2_index] {
|
||||||
0 => {
|
0 => {
|
||||||
|
let initial_data = if let Some(backing) = self.backing_file.as_mut() {
|
||||||
|
let cluster_size = self.raw_file.cluster_size();
|
||||||
|
let cluster_begin = address - (address % cluster_size);
|
||||||
|
let mut cluster_data = vec![0u8; cluster_size as usize];
|
||||||
|
backing.seek(SeekFrom::Start(cluster_begin))?;
|
||||||
|
backing.read_exact(&mut cluster_data)?;
|
||||||
|
Some(cluster_data)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
// Need to allocate a data cluster
|
// Need to allocate a data cluster
|
||||||
let cluster_addr = self.append_data_cluster()?;
|
let cluster_addr = self.append_data_cluster(initial_data)?;
|
||||||
self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
|
self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
|
||||||
cluster_addr
|
cluster_addr
|
||||||
}
|
}
|
||||||
@@ -1066,7 +1175,7 @@ impl QcowFile {
|
|||||||
// Allocate a new cluster to store the L2 table and update the L1 table to point
|
// Allocate a new cluster to store the L2 table and update the L1 table to point
|
||||||
// to the new table. The cluster will be written when the cache is flushed, no
|
// to the new table. The cluster will be written when the cache is flushed, no
|
||||||
// need to copy the data now.
|
// need to copy the data now.
|
||||||
let new_addr: u64 = self.get_new_cluster()?;
|
let new_addr: u64 = self.get_new_cluster(None)?;
|
||||||
// The cluster refcount starts at one indicating it is used but doesn't need
|
// The cluster refcount starts at one indicating it is used but doesn't need
|
||||||
// COW.
|
// COW.
|
||||||
set_refcounts.push((new_addr, 1));
|
set_refcounts.push((new_addr, 1));
|
||||||
@@ -1078,15 +1187,22 @@ impl QcowFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new cluster and return its offset within the raw file.
|
// Allocate a new cluster and return its offset within the raw file.
|
||||||
fn get_new_cluster(&mut self) -> std::io::Result<u64> {
|
fn get_new_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64> {
|
||||||
// First use a pre allocated cluster if one is available.
|
// First use a pre allocated cluster if one is available.
|
||||||
if let Some(free_cluster) = self.avail_clusters.pop() {
|
if let Some(free_cluster) = self.avail_clusters.pop() {
|
||||||
self.raw_file.zero_cluster(free_cluster)?;
|
if let Some(initial_data) = initial_data {
|
||||||
|
self.raw_file.write_cluster(free_cluster, initial_data)?;
|
||||||
|
} else {
|
||||||
|
self.raw_file.zero_cluster(free_cluster)?;
|
||||||
|
}
|
||||||
return Ok(free_cluster);
|
return Ok(free_cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_valid_cluster_offset = self.refcounts.max_valid_cluster_offset();
|
let max_valid_cluster_offset = self.refcounts.max_valid_cluster_offset();
|
||||||
if let Some(new_cluster) = self.raw_file.add_cluster_end(max_valid_cluster_offset)? {
|
if let Some(new_cluster) = self.raw_file.add_cluster_end(max_valid_cluster_offset)? {
|
||||||
|
if let Some(initial_data) = initial_data {
|
||||||
|
self.raw_file.write_cluster(new_cluster, initial_data)?;
|
||||||
|
}
|
||||||
Ok(new_cluster)
|
Ok(new_cluster)
|
||||||
} else {
|
} else {
|
||||||
error!("No free clusters in get_new_cluster()");
|
error!("No free clusters in get_new_cluster()");
|
||||||
@@ -1096,8 +1212,8 @@ impl QcowFile {
|
|||||||
|
|
||||||
// Allocate and initialize a new data cluster. Returns the offset of the
|
// Allocate and initialize a new data cluster. Returns the offset of the
|
||||||
// cluster in to the file on success.
|
// cluster in to the file on success.
|
||||||
fn append_data_cluster(&mut self) -> std::io::Result<u64> {
|
fn append_data_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64> {
|
||||||
let new_addr: u64 = self.get_new_cluster()?;
|
let new_addr: u64 = self.get_new_cluster(initial_data)?;
|
||||||
// The cluster refcount starts at one indicating it is used but doesn't need COW.
|
// The cluster refcount starts at one indicating it is used but doesn't need COW.
|
||||||
let mut newly_unref = self.set_cluster_refcount(new_addr, 1)?;
|
let mut newly_unref = self.set_cluster_refcount(new_addr, 1)?;
|
||||||
self.unref_clusters.append(&mut newly_unref);
|
self.unref_clusters.append(&mut newly_unref);
|
||||||
@@ -1331,7 +1447,7 @@ impl QcowFile {
|
|||||||
}
|
}
|
||||||
Err(refcount::Error::NeedNewCluster) => {
|
Err(refcount::Error::NeedNewCluster) => {
|
||||||
// Allocate the cluster and call set_cluster_refcount again.
|
// Allocate the cluster and call set_cluster_refcount again.
|
||||||
let addr = self.get_new_cluster()?;
|
let addr = self.get_new_cluster(None)?;
|
||||||
added_clusters.push(addr);
|
added_clusters.push(addr);
|
||||||
new_cluster = Some((
|
new_cluster = Some((
|
||||||
addr,
|
addr,
|
||||||
@@ -1414,6 +1530,9 @@ impl Read for QcowFile {
|
|||||||
self.raw_file
|
self.raw_file
|
||||||
.file_mut()
|
.file_mut()
|
||||||
.read_exact(&mut buf[nread..(nread + count)])?;
|
.read_exact(&mut buf[nread..(nread + count)])?;
|
||||||
|
} else if let Some(backing) = self.backing_file.as_mut() {
|
||||||
|
backing.seek(SeekFrom::Start(curr_addr))?;
|
||||||
|
backing.read_exact(&mut buf[nread..(nread + count)])?;
|
||||||
} else {
|
} else {
|
||||||
// Previously unwritten region, return zeros
|
// Previously unwritten region, return zeros
|
||||||
for b in &mut buf[nread..(nread + count)] {
|
for b in &mut buf[nread..(nread + count)] {
|
||||||
@@ -1556,6 +1675,12 @@ impl SeekHole for QcowFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for QcowFile {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.virtual_size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an Error if the given offset doesn't align to a cluster boundary.
|
// Returns an Error if the given offset doesn't align to a cluster boundary.
|
||||||
fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
|
fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
|
||||||
if offset & ((0x01 << cluster_bits) - 1) != 0 {
|
if offset & ((0x01 << cluster_bits) - 1) != 0 {
|
||||||
@@ -1766,16 +1891,19 @@ mod tests {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_basic_file<F>(header: &[u8], mut testfn: F)
|
fn basic_file(header: &[u8]) -> RawFile {
|
||||||
where
|
|
||||||
F: FnMut(RawFile),
|
|
||||||
{
|
|
||||||
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
||||||
disk_file.write_all(header).unwrap();
|
disk_file.write_all(header).unwrap();
|
||||||
disk_file.set_len(0x1_0000_0000).unwrap();
|
disk_file.set_len(0x1_0000_0000).unwrap();
|
||||||
disk_file.rewind().unwrap();
|
disk_file.rewind().unwrap();
|
||||||
|
disk_file
|
||||||
|
}
|
||||||
|
|
||||||
testfn(disk_file); // File closed when the function exits.
|
fn with_basic_file<F>(header: &[u8], mut testfn: F)
|
||||||
|
where
|
||||||
|
F: FnMut(RawFile),
|
||||||
|
{
|
||||||
|
testfn(basic_file(header)); // File closed when the function exits.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_default_file<F>(file_size: u64, direct: bool, mut testfn: F)
|
fn with_default_file<F>(file_size: u64, direct: bool, mut testfn: F)
|
||||||
@@ -1788,11 +1916,44 @@ mod tests {
|
|||||||
testfn(qcow_file); // File closed when the function exits.
|
testfn(qcow_file); // File closed when the function exits.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_read_start_backing_v2() {
|
||||||
|
let disk_file = basic_file(&valid_header_v2());
|
||||||
|
let mut backing = QcowFile::from(disk_file).unwrap();
|
||||||
|
backing
|
||||||
|
.write_all(b"test first bytes")
|
||||||
|
.expect("Failed to write test string.");
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
let wrapping_disk_file = basic_file(&valid_header_v2());
|
||||||
|
let mut wrapping = QcowFile::from(wrapping_disk_file).unwrap();
|
||||||
|
wrapping.set_backing_file(Some(Box::new(backing)));
|
||||||
|
wrapping.seek(SeekFrom::Start(0)).expect("Failed to seek.");
|
||||||
|
wrapping.read_exact(&mut buf).expect("Failed to read.");
|
||||||
|
assert_eq!(&buf, b"test");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_read_start_backing_v3() {
|
||||||
|
let disk_file = basic_file(&valid_header_v3());
|
||||||
|
let mut backing = QcowFile::from(disk_file).unwrap();
|
||||||
|
backing
|
||||||
|
.write_all(b"test first bytes")
|
||||||
|
.expect("Failed to write test string.");
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
let wrapping_disk_file = basic_file(&valid_header_v3());
|
||||||
|
let mut wrapping = QcowFile::from(wrapping_disk_file).unwrap();
|
||||||
|
wrapping.set_backing_file(Some(Box::new(backing)));
|
||||||
|
wrapping.seek(SeekFrom::Start(0)).expect("Failed to seek.");
|
||||||
|
wrapping.read_exact(&mut buf).expect("Failed to read.");
|
||||||
|
assert_eq!(&buf, b"test");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_header_v2() {
|
fn default_header_v2() {
|
||||||
let header = QcowHeader::create_for_size(2, 0x10_0000);
|
let header = QcowHeader::create_for_size_and_path(2, 0x10_0000, None);
|
||||||
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
||||||
header
|
header
|
||||||
|
.expect("Failed to create header.")
|
||||||
.write_to(&mut disk_file)
|
.write_to(&mut disk_file)
|
||||||
.expect("Failed to write header to temporary file.");
|
.expect("Failed to write header to temporary file.");
|
||||||
disk_file.rewind().unwrap();
|
disk_file.rewind().unwrap();
|
||||||
@@ -1801,9 +1962,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_header_v3() {
|
fn default_header_v3() {
|
||||||
let header = QcowHeader::create_for_size(3, 0x10_0000);
|
let header = QcowHeader::create_for_size_and_path(3, 0x10_0000, None);
|
||||||
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
||||||
header
|
header
|
||||||
|
.expect("Failed to create header.")
|
||||||
.write_to(&mut disk_file)
|
.write_to(&mut disk_file)
|
||||||
.expect("Failed to write header to temporary file.");
|
.expect("Failed to write header to temporary file.");
|
||||||
disk_file.rewind().unwrap();
|
disk_file.rewind().unwrap();
|
||||||
@@ -1826,6 +1988,40 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn header_v2_with_backing() {
|
||||||
|
let header = QcowHeader::create_for_size_and_path(2, 0x10_0000, Some("/my/path/to/a/file"))
|
||||||
|
.expect("Failed to create header.");
|
||||||
|
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
||||||
|
header
|
||||||
|
.write_to(&mut disk_file)
|
||||||
|
.expect("Failed to write header to shm.");
|
||||||
|
disk_file.rewind().unwrap();
|
||||||
|
let read_header = QcowHeader::new(&mut disk_file).expect("Failed to create header.");
|
||||||
|
assert_eq!(
|
||||||
|
header.backing_file_path,
|
||||||
|
Some(String::from("/my/path/to/a/file"))
|
||||||
|
);
|
||||||
|
assert_eq!(read_header.backing_file_path, header.backing_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn header_v3_with_backing() {
|
||||||
|
let header = QcowHeader::create_for_size_and_path(3, 0x10_0000, Some("/my/path/to/a/file"))
|
||||||
|
.expect("Failed to create header.");
|
||||||
|
let mut disk_file: RawFile = RawFile::new(TempFile::new().unwrap().into_file(), false);
|
||||||
|
header
|
||||||
|
.write_to(&mut disk_file)
|
||||||
|
.expect("Failed to write header to shm.");
|
||||||
|
disk_file.rewind().unwrap();
|
||||||
|
let read_header = QcowHeader::new(&mut disk_file).expect("Failed to create header.");
|
||||||
|
assert_eq!(
|
||||||
|
header.backing_file_path,
|
||||||
|
Some(String::from("/my/path/to/a/file"))
|
||||||
|
);
|
||||||
|
assert_eq!(read_header.backing_file_path, header.backing_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_magic() {
|
fn invalid_magic() {
|
||||||
let invalid_header = vec![0x51u8, 0x46, 0x4a, 0xfb];
|
let invalid_header = vec![0x51u8, 0x46, 0x4a, 0xfb];
|
||||||
@@ -1940,6 +2136,26 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_read_start_backing_overlap() {
|
||||||
|
let disk_file = basic_file(&valid_header_v3());
|
||||||
|
let mut backing = QcowFile::from(disk_file).unwrap();
|
||||||
|
backing
|
||||||
|
.write_all(b"test first bytes")
|
||||||
|
.expect("Failed to write test string.");
|
||||||
|
let wrapping_disk_file = basic_file(&valid_header_v3());
|
||||||
|
let mut wrapping = QcowFile::from(wrapping_disk_file).unwrap();
|
||||||
|
wrapping.set_backing_file(Some(Box::new(backing)));
|
||||||
|
wrapping.seek(SeekFrom::Start(0)).expect("Failed to seek.");
|
||||||
|
wrapping
|
||||||
|
.write_all(b"TEST")
|
||||||
|
.expect("Failed to write second test string.");
|
||||||
|
let mut buf = [0u8; 10];
|
||||||
|
wrapping.seek(SeekFrom::Start(0)).expect("Failed to seek.");
|
||||||
|
wrapping.read_exact(&mut buf).expect("Failed to read.");
|
||||||
|
assert_eq!(&buf, b"TEST first");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn offset_write_read() {
|
fn offset_write_read() {
|
||||||
with_basic_file(&valid_header_v3(), |disk_file: RawFile| {
|
with_basic_file(&valid_header_v3(), |disk_file: RawFile| {
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use super::RawFile;
|
use super::RawFile;
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use std::io::{self, BufWriter, Seek, SeekFrom};
|
use std::io::{self, BufWriter, Seek, SeekFrom, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use vmm_sys_util::write_zeroes::WriteZeroes;
|
use vmm_sys_util::write_zeroes::WriteZeroes;
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ impl QcowRawFile {
|
|||||||
non_zero_flags: u64,
|
non_zero_flags: u64,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
self.file.seek(SeekFrom::Start(offset))?;
|
self.file.seek(SeekFrom::Start(offset))?;
|
||||||
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u64>(), &mut self.file);
|
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
|
||||||
for addr in table {
|
for addr in table {
|
||||||
let val = if *addr == 0 {
|
let val = if *addr == 0 {
|
||||||
0
|
0
|
||||||
@@ -91,7 +91,8 @@ impl QcowRawFile {
|
|||||||
/// Writes a refcount block to the file.
|
/// Writes a refcount block to the file.
|
||||||
pub fn write_refcount_block(&mut self, offset: u64, table: &[u16]) -> io::Result<()> {
|
pub fn write_refcount_block(&mut self, offset: u64, table: &[u16]) -> io::Result<()> {
|
||||||
self.file.seek(SeekFrom::Start(offset))?;
|
self.file.seek(SeekFrom::Start(offset))?;
|
||||||
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u16>(), &mut self.file);
|
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
|
||||||
|
|
||||||
for count in table {
|
for count in table {
|
||||||
buffer.write_u16::<BigEndian>(*count)?;
|
buffer.write_u16::<BigEndian>(*count)?;
|
||||||
}
|
}
|
||||||
@@ -136,6 +137,13 @@ impl QcowRawFile {
|
|||||||
self.file.write_zeroes(cluster_size)?;
|
self.file.write_zeroes(cluster_size)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Writes
|
||||||
|
pub fn write_cluster(&mut self, address: u64, data: Vec<u8>) -> io::Result<()> {
|
||||||
|
let cluster_size = self.cluster_size as usize;
|
||||||
|
self.file.seek(SeekFrom::Start(address))?;
|
||||||
|
self.file.write_all(&data[0..cluster_size])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for QcowRawFile {
|
impl Clone for QcowRawFile {
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
|
use crate::BlockBackend;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@@ -22,6 +23,7 @@ pub struct RawFile {
|
|||||||
file: File,
|
file: File,
|
||||||
alignment: usize,
|
alignment: usize,
|
||||||
position: u64,
|
position: u64,
|
||||||
|
direct_io: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const BLK_ALIGNMENTS: [usize; 2] = [512, 4096];
|
const BLK_ALIGNMENTS: [usize; 2] = [512, 4096];
|
||||||
@@ -64,6 +66,7 @@ impl RawFile {
|
|||||||
file,
|
file,
|
||||||
alignment,
|
alignment,
|
||||||
position: 0,
|
position: 0,
|
||||||
|
direct_io,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +105,7 @@ impl RawFile {
|
|||||||
file: self.file.try_clone().expect("RawFile cloning failed"),
|
file: self.file.try_clone().expect("RawFile cloning failed"),
|
||||||
alignment: self.alignment,
|
alignment: self.alignment,
|
||||||
position: self.position,
|
position: self.position,
|
||||||
|
direct_io: self.direct_io,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +116,10 @@ impl RawFile {
|
|||||||
pub fn sync_data(&self) -> std::io::Result<()> {
|
pub fn sync_data(&self) -> std::io::Result<()> {
|
||||||
self.file.sync_data()
|
self.file.sync_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_direct(&self) -> bool {
|
||||||
|
self.direct_io
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for RawFile {
|
impl Read for RawFile {
|
||||||
@@ -343,12 +351,19 @@ impl SeekHole for RawFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for RawFile {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.metadata().map_err(crate::Error::RawFileError)?.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for RawFile {
|
impl Clone for RawFile {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
RawFile {
|
RawFile {
|
||||||
file: self.file.try_clone().expect("RawFile cloning failed"),
|
file: self.file.try_clone().expect("RawFile cloning failed"),
|
||||||
alignment: self.alignment,
|
alignment: self.alignment,
|
||||||
position: self.position,
|
position: self.position,
|
||||||
|
direct_io: self.direct_io,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,10 @@ use std::io;
|
|||||||
|
|
||||||
use libc::EINVAL;
|
use libc::EINVAL;
|
||||||
|
|
||||||
use crate::qcow_raw_file::QcowRawFile;
|
use crate::qcow::{
|
||||||
use crate::vec_cache::{CacheMap, Cacheable, VecCache};
|
qcow_raw_file::QcowRawFile,
|
||||||
|
vec_cache::{CacheMap, Cacheable, VecCache},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
|
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
|
||||||
|
use crate::qcow::{QcowFile, RawFile, Result as QcowResult};
|
||||||
use crate::AsyncAdaptor;
|
use crate::AsyncAdaptor;
|
||||||
use qcow::{QcowFile, RawFile, Result as QcowResult};
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
@@ -86,7 +86,7 @@ impl AsyncIo for RawFileAsync {
|
|||||||
let _ = unsafe {
|
let _ = unsafe {
|
||||||
sq.push(
|
sq.push(
|
||||||
&opcode::Readv::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
|
&opcode::Readv::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
|
||||||
.offset(offset)
|
.offset(offset.try_into().unwrap())
|
||||||
.build()
|
.build()
|
||||||
.flags(squeue::Flags::ASYNC)
|
.flags(squeue::Flags::ASYNC)
|
||||||
.user_data(user_data),
|
.user_data(user_data),
|
||||||
@@ -114,7 +114,7 @@ impl AsyncIo for RawFileAsync {
|
|||||||
let _ = unsafe {
|
let _ = unsafe {
|
||||||
sq.push(
|
sq.push(
|
||||||
&opcode::Writev::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
|
&opcode::Writev::new(types::Fd(self.fd), iovecs.as_ptr(), iovecs.len() as u32)
|
||||||
.offset(offset)
|
.offset(offset.try_into().unwrap())
|
||||||
.build()
|
.build()
|
||||||
.flags(squeue::Flags::ASYNC)
|
.flags(squeue::Flags::ASYNC)
|
||||||
.user_data(user_data),
|
.user_data(user_data),
|
||||||
@@ -73,7 +73,7 @@ impl AsyncIo for RawFileSync {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
libc::preadv(
|
libc::preadv(
|
||||||
self.fd as libc::c_int,
|
self.fd as libc::c_int,
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
iovecs.as_ptr(),
|
||||||
iovecs.len() as libc::c_int,
|
iovecs.len() as libc::c_int,
|
||||||
offset,
|
offset,
|
||||||
)
|
)
|
||||||
@@ -98,7 +98,7 @@ impl AsyncIo for RawFileSync {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
libc::pwritev(
|
libc::pwritev(
|
||||||
self.fd as libc::c_int,
|
self.fd as libc::c_int,
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
iovecs.as_ptr(),
|
||||||
iovecs.len() as libc::c_int,
|
iovecs.len() as libc::c_int,
|
||||||
offset,
|
offset,
|
||||||
)
|
)
|
||||||
@@ -2,15 +2,31 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::vhdx_bat::{BatEntry, VhdxBatError};
|
use crate::vhdx::{
|
||||||
use crate::vhdx_header::{self, RegionInfo, RegionTableEntry, VhdxHeader, VhdxHeaderError};
|
vhdx_bat::{BatEntry, VhdxBatError},
|
||||||
use crate::vhdx_io::{self, VhdxIoError};
|
vhdx_header::{RegionInfo, RegionTableEntry, VhdxHeader, VhdxHeaderError},
|
||||||
use crate::vhdx_metadata::{DiskSpec, VhdxMetadataError};
|
vhdx_io::VhdxIoError,
|
||||||
|
vhdx_metadata::{DiskSpec, VhdxMetadataError},
|
||||||
|
};
|
||||||
|
use crate::BlockBackend;
|
||||||
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::collections::btree_map::BTreeMap;
|
use std::collections::btree_map::BTreeMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
macro_rules! div_round_up {
|
||||||
|
($n:expr,$d:expr) => {
|
||||||
|
($n + $d - 1) / $d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mod vhdx_bat;
|
||||||
|
mod vhdx_header;
|
||||||
|
mod vhdx_io;
|
||||||
|
mod vhdx_metadata;
|
||||||
|
|
||||||
#[sorted]
|
#[sorted]
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@@ -193,6 +209,12 @@ impl Seek for Vhdx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockBackend for Vhdx {
|
||||||
|
fn size(&self) -> std::result::Result<u64, crate::Error> {
|
||||||
|
Ok(self.virtual_disk_size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for Vhdx {
|
impl Clone for Vhdx {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Vhdx {
|
Vhdx {
|
||||||
@@ -208,3 +230,15 @@ impl Clone for Vhdx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn uuid_from_guid(buf: &[u8]) -> Uuid {
|
||||||
|
// The first 3 fields of UUID are stored in Big Endian format, and
|
||||||
|
// the last 8 bytes are stored as byte array. Therefore, we read the
|
||||||
|
// first 3 fields in Big Endian format instead of Little Endian.
|
||||||
|
Uuid::from_fields_le(
|
||||||
|
BigEndian::read_u32(&buf[0..4]),
|
||||||
|
BigEndian::read_u16(&buf[4..6]),
|
||||||
|
BigEndian::read_u16(&buf[6..8]),
|
||||||
|
buf[8..16].try_into().unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::vhdx_header::RegionTableEntry;
|
use crate::vhdx::{vhdx_header::RegionTableEntry, vhdx_metadata::DiskSpec};
|
||||||
use crate::vhdx_metadata::DiskSpec;
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -344,7 +344,7 @@ impl RegionTableEntry {
|
|||||||
// SAFETY: the assertion above makes sure the buffer size is correct.
|
// SAFETY: the assertion above makes sure the buffer size is correct.
|
||||||
let mut region_table_entry = unsafe { *(buffer.as_ptr() as *mut RegionTableEntry) };
|
let mut region_table_entry = unsafe { *(buffer.as_ptr() as *mut RegionTableEntry) };
|
||||||
|
|
||||||
let uuid = crate::uuid_from_guid(buffer);
|
let uuid = crate::vhdx::uuid_from_guid(buffer);
|
||||||
region_table_entry.guid = uuid;
|
region_table_entry.guid = uuid;
|
||||||
|
|
||||||
Ok(region_table_entry)
|
Ok(region_table_entry)
|
||||||
@@ -2,8 +2,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::vhdx_bat::{self, BatEntry, VhdxBatError};
|
use crate::vhdx::{
|
||||||
use crate::vhdx_metadata::{self, DiskSpec};
|
vhdx_bat::{self, BatEntry, VhdxBatError},
|
||||||
|
vhdx_metadata::{self, DiskSpec},
|
||||||
|
};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::vhdx_header::RegionTableEntry;
|
use crate::vhdx::vhdx_header::RegionTableEntry;
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use remain::sorted;
|
use remain::sorted;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -145,11 +145,7 @@ impl DiskSpec {
|
|||||||
let bits = f
|
let bits = f
|
||||||
.read_u32::<LittleEndian>()
|
.read_u32::<LittleEndian>()
|
||||||
.map_err(VhdxMetadataError::ReadMetadata)?;
|
.map_err(VhdxMetadataError::ReadMetadata)?;
|
||||||
if bits & BLOCK_HAS_PARENT != 0 {
|
disk_spec.has_parent = bits & BLOCK_HAS_PARENT != 0;
|
||||||
disk_spec.has_parent = true;
|
|
||||||
} else {
|
|
||||||
disk_spec.has_parent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata_presence |= METADATA_FILE_PARAMETER_PRESENT;
|
metadata_presence |= METADATA_FILE_PARAMETER_PRESENT;
|
||||||
} else if metadata_entry.item_id
|
} else if metadata_entry.item_id
|
||||||
@@ -307,7 +303,7 @@ impl MetadataTableEntry {
|
|||||||
// SAFETY: the assertion above makes sure the buffer size is correct.
|
// SAFETY: the assertion above makes sure the buffer size is correct.
|
||||||
let mut metadata_table_entry = unsafe { *(buffer.as_ptr() as *mut MetadataTableEntry) };
|
let mut metadata_table_entry = unsafe { *(buffer.as_ptr() as *mut MetadataTableEntry) };
|
||||||
|
|
||||||
let uuid = crate::uuid_from_guid(buffer);
|
let uuid = crate::vhdx::uuid_from_guid(buffer);
|
||||||
metadata_table_entry.item_id = uuid;
|
metadata_table_entry.item_id = uuid;
|
||||||
|
|
||||||
if metadata_table_entry.length > METADATA_LENGTH_MAX {
|
if metadata_table_entry.length > METADATA_LENGTH_MAX {
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
|
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
|
||||||
|
use crate::vhdx::{Result as VhdxResult, Vhdx};
|
||||||
use crate::AsyncAdaptor;
|
use crate::AsyncAdaptor;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use vhdx::vhdx::{Result as VhdxResult, Vhdx};
|
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct VhdxDiskSync {
|
pub struct VhdxDiskSync {
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "block_util"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
io-uring = "0.5.12"
|
|
||||||
libc = "0.2.139"
|
|
||||||
log = "0.4.17"
|
|
||||||
qcow = { path = "../qcow" }
|
|
||||||
smallvec = "1.10.0"
|
|
||||||
thiserror = "1.0.38"
|
|
||||||
versionize = "0.1.9"
|
|
||||||
versionize_derive = "0.1.4"
|
|
||||||
vhdx = { path = "../vhdx" }
|
|
||||||
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
|
||||||
virtio-queue = "0.7.0"
|
|
||||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
|
||||||
vmm-sys-util = "0.11.0"
|
|
||||||
|
|
||||||
4
build.rs
4
build.rs
@@ -17,8 +17,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This println!() has a special behavior, as it will set the environment
|
// This println!() has a special behavior, as it will set the environment
|
||||||
// variable BUILT_VERSION, so that it can be reused from the binary.
|
// variable BUILD_VERSION, so that it can be reused from the binary.
|
||||||
// Particularly, this is used from src/main.rs to display the exact
|
// Particularly, this is used from src/main.rs to display the exact
|
||||||
// version.
|
// version.
|
||||||
println!("cargo:rustc-env=BUILT_VERSION={version}");
|
println!("cargo:rustc-env=BUILD_VERSION={version}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,19 +6,22 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.71"
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
bitflags = "1.3.2"
|
bitflags = "2.3.3"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
|
event_monitor = { path = "../event_monitor" }
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
thiserror = "1.0.38"
|
pci = { path = "../pci" }
|
||||||
|
thiserror = "1.0.40"
|
||||||
tpm = { path = "../tpm" }
|
tpm = { path = "../tpm" }
|
||||||
versionize = "0.1.9"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.10.0"
|
vm-memory = "0.11.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
use super::AcpiNotificationFlags;
|
use super::AcpiNotificationFlags;
|
||||||
use acpi_tables::{aml, aml::Aml};
|
use acpi_tables::{aml, Aml, AmlSink};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
|
use std::thread;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use vm_device::interrupt::InterruptSourceGroup;
|
use vm_device::interrupt::InterruptSourceGroup;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
@@ -18,14 +20,20 @@ pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
|
|||||||
pub struct AcpiShutdownDevice {
|
pub struct AcpiShutdownDevice {
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
reset_evt: EventFd,
|
reset_evt: EventFd,
|
||||||
|
vcpus_kill_signalled: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AcpiShutdownDevice {
|
impl AcpiShutdownDevice {
|
||||||
/// Constructs a device that will signal the given event when the guest requests it.
|
/// Constructs a device that will signal the given event when the guest requests it.
|
||||||
pub fn new(exit_evt: EventFd, reset_evt: EventFd) -> AcpiShutdownDevice {
|
pub fn new(
|
||||||
|
exit_evt: EventFd,
|
||||||
|
reset_evt: EventFd,
|
||||||
|
vcpus_kill_signalled: Arc<AtomicBool>,
|
||||||
|
) -> AcpiShutdownDevice {
|
||||||
AcpiShutdownDevice {
|
AcpiShutdownDevice {
|
||||||
exit_evt,
|
exit_evt,
|
||||||
reset_evt,
|
reset_evt,
|
||||||
|
vcpus_kill_signalled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,6 +51,13 @@ impl BusDevice for AcpiShutdownDevice {
|
|||||||
if let Err(e) = self.reset_evt.write(1) {
|
if let Err(e) = self.reset_evt.write(1) {
|
||||||
error!("Error triggering ACPI reset event: {}", e);
|
error!("Error triggering ACPI reset event: {}", e);
|
||||||
}
|
}
|
||||||
|
// Spin until we are sure the reset_evt has been handled and that when
|
||||||
|
// we return from the KVM_RUN we will exit rather than re-enter the guest.
|
||||||
|
while !self.vcpus_kill_signalled.load(Ordering::SeqCst) {
|
||||||
|
// This is more effective than thread::yield_now() at
|
||||||
|
// avoiding a priority inversion with the VMM thread
|
||||||
|
thread::sleep(std::time::Duration::from_millis(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// The ACPI DSDT table specifies the S5 sleep state (shutdown) as value 5
|
// The ACPI DSDT table specifies the S5 sleep state (shutdown) as value 5
|
||||||
const S5_SLEEP_VALUE: u8 = 5;
|
const S5_SLEEP_VALUE: u8 = 5;
|
||||||
@@ -53,6 +68,13 @@ impl BusDevice for AcpiShutdownDevice {
|
|||||||
if let Err(e) = self.exit_evt.write(1) {
|
if let Err(e) = self.exit_evt.write(1) {
|
||||||
error!("Error triggering ACPI shutdown event: {}", e);
|
error!("Error triggering ACPI shutdown event: {}", e);
|
||||||
}
|
}
|
||||||
|
// Spin until we are sure the reset_evt has been handled and that when
|
||||||
|
// we return from the KVM_RUN we will exit rather than re-enter the guest.
|
||||||
|
while !self.vcpus_kill_signalled.load(Ordering::SeqCst) {
|
||||||
|
// This is more effective than thread::yield_now() at
|
||||||
|
// avoiding a priority inversion with the VMM thread
|
||||||
|
thread::sleep(std::time::Duration::from_millis(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -103,11 +125,11 @@ impl BusDevice for AcpiGedDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for AcpiGedDevice {
|
impl Aml for AcpiGedDevice {
|
||||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
|
||||||
aml::Device::new(
|
aml::Device::new(
|
||||||
"_SB_.GEC_".into(),
|
"_SB_.GEC_".into(),
|
||||||
vec![
|
vec![
|
||||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||||
&aml::Name::new("_UID".into(), &"Generic Event Controller"),
|
&aml::Name::new("_UID".into(), &"Generic Event Controller"),
|
||||||
&aml::Name::new(
|
&aml::Name::new(
|
||||||
"_CRS".into(),
|
"_CRS".into(),
|
||||||
@@ -116,17 +138,19 @@ impl Aml for AcpiGedDevice {
|
|||||||
true,
|
true,
|
||||||
self.address.0,
|
self.address.0,
|
||||||
self.address.0 + GED_DEVICE_ACPI_SIZE as u64 - 1,
|
self.address.0 + GED_DEVICE_ACPI_SIZE as u64 - 1,
|
||||||
|
None,
|
||||||
)]),
|
)]),
|
||||||
),
|
),
|
||||||
&aml::OpRegion::new(
|
&aml::OpRegion::new(
|
||||||
"GDST".into(),
|
"GDST".into(),
|
||||||
aml::OpRegionSpace::SystemMemory,
|
aml::OpRegionSpace::SystemMemory,
|
||||||
self.address.0 as usize,
|
&(self.address.0 as usize),
|
||||||
GED_DEVICE_ACPI_SIZE,
|
&GED_DEVICE_ACPI_SIZE,
|
||||||
),
|
),
|
||||||
&aml::Field::new(
|
&aml::Field::new(
|
||||||
"GDST".into(),
|
"GDST".into(),
|
||||||
aml::FieldAccessType::Byte,
|
aml::FieldAccessType::Byte,
|
||||||
|
aml::FieldLockRule::NoLock,
|
||||||
aml::FieldUpdateRule::WriteAsZeroes,
|
aml::FieldUpdateRule::WriteAsZeroes,
|
||||||
vec![aml::FieldEntry::Named(*b"GDAT", 8)],
|
vec![aml::FieldEntry::Named(*b"GDAT", 8)],
|
||||||
),
|
),
|
||||||
@@ -163,7 +187,7 @@ impl Aml for AcpiGedDevice {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.append_aml_bytes(bytes);
|
.to_aml_bytes(sink);
|
||||||
aml::Device::new(
|
aml::Device::new(
|
||||||
"_SB_.GED_".into(),
|
"_SB_.GED_".into(),
|
||||||
vec![
|
vec![
|
||||||
@@ -187,7 +211,7 @@ impl Aml for AcpiGedDevice {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.append_aml_bytes(bytes)
|
.to_aml_bytes(sink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,9 +98,14 @@ impl Gic {
|
|||||||
i as InterruptIndex,
|
i as InterruptIndex,
|
||||||
InterruptSourceConfig::LegacyIrq(config),
|
InterruptSourceConfig::LegacyIrq(config),
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.map_err(Error::EnableInterrupt)?;
|
.map_err(Error::EnableInterrupt)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.interrupt_source_group
|
||||||
|
.set_gsi()
|
||||||
|
.map_err(Error::EnableInterrupt)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -237,9 +237,14 @@ impl Ioapic {
|
|||||||
if state.is_some() {
|
if state.is_some() {
|
||||||
for (irq, entry) in ioapic.used_entries.iter().enumerate() {
|
for (irq, entry) in ioapic.used_entries.iter().enumerate() {
|
||||||
if *entry {
|
if *entry {
|
||||||
ioapic.update_entry(irq)?;
|
ioapic.update_entry(irq, false)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ioapic
|
||||||
|
.interrupt_source_group
|
||||||
|
.set_gsi()
|
||||||
|
.map_err(Error::UpdateInterrupt)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ioapic)
|
Ok(ioapic)
|
||||||
@@ -278,7 +283,7 @@ impl Ioapic {
|
|||||||
}
|
}
|
||||||
// The entry must be updated through the interrupt source
|
// The entry must be updated through the interrupt source
|
||||||
// group.
|
// group.
|
||||||
if let Err(e) = self.update_entry(index) {
|
if let Err(e) = self.update_entry(index, true) {
|
||||||
error!("Failed updating IOAPIC entry: {:?}", e);
|
error!("Failed updating IOAPIC entry: {:?}", e);
|
||||||
}
|
}
|
||||||
// Store the information this IRQ is now being used.
|
// Store the information this IRQ is now being used.
|
||||||
@@ -329,7 +334,7 @@ impl Ioapic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_entry(&self, irq: usize) -> Result<()> {
|
fn update_entry(&self, irq: usize, set_gsi: bool) -> Result<()> {
|
||||||
let entry = self.reg_entries[irq];
|
let entry = self.reg_entries[irq];
|
||||||
|
|
||||||
// Validate Destination Mode value, and retrieve Destination ID
|
// Validate Destination Mode value, and retrieve Destination ID
|
||||||
@@ -386,6 +391,7 @@ impl Ioapic {
|
|||||||
irq as InterruptIndex,
|
irq as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
interrupt_mask(entry) == 1,
|
interrupt_mask(entry) == 1,
|
||||||
|
set_gsi,
|
||||||
)
|
)
|
||||||
.map_err(Error::UpdateInterrupt)?;
|
.map_err(Error::UpdateInterrupt)?;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
use libc::{clock_gettime, gmtime_r, timespec, tm, CLOCK_REALTIME};
|
use libc::{clock_gettime, gmtime_r, timespec, tm, CLOCK_REALTIME};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier};
|
||||||
|
use std::thread;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
@@ -23,13 +25,19 @@ pub struct Cmos {
|
|||||||
index: u8,
|
index: u8,
|
||||||
data: [u8; DATA_LEN],
|
data: [u8; DATA_LEN],
|
||||||
reset_evt: EventFd,
|
reset_evt: EventFd,
|
||||||
|
vcpus_kill_signalled: Option<Arc<AtomicBool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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, reset_evt: EventFd) -> Cmos {
|
pub fn new(
|
||||||
|
mem_below_4g: u64,
|
||||||
|
mem_above_4g: u64,
|
||||||
|
reset_evt: EventFd,
|
||||||
|
vcpus_kill_signalled: Option<Arc<AtomicBool>>,
|
||||||
|
) -> 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
|
||||||
@@ -50,6 +58,7 @@ impl Cmos {
|
|||||||
index: 0,
|
index: 0,
|
||||||
data,
|
data,
|
||||||
reset_evt,
|
reset_evt,
|
||||||
|
vcpus_kill_signalled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,6 +76,15 @@ impl BusDevice for Cmos {
|
|||||||
if self.index == 0x8f && data[0] == 0 {
|
if self.index == 0x8f && data[0] == 0 {
|
||||||
info!("CMOS reset");
|
info!("CMOS reset");
|
||||||
self.reset_evt.write(1).unwrap();
|
self.reset_evt.write(1).unwrap();
|
||||||
|
if let Some(vcpus_kill_signalled) = self.vcpus_kill_signalled.take() {
|
||||||
|
// Spin until we are sure the reset_evt has been handled and that when
|
||||||
|
// we return from the KVM_RUN we will exit rather than re-enter the guest.
|
||||||
|
while !vcpus_kill_signalled.load(Ordering::SeqCst) {
|
||||||
|
// This is more effective than thread::yield_now() at
|
||||||
|
// avoiding a priority inversion with the VMM thread
|
||||||
|
thread::sleep(std::time::Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.data[(self.index & INDEX_MASK) as usize] = data[0]
|
self.data[(self.index & INDEX_MASK) as usize] = data[0]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,10 +361,15 @@ mod tests {
|
|||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
_masked: bool,
|
_masked: bool,
|
||||||
|
_set_gsi: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||||
Some(self.event_fd.try_clone().unwrap())
|
Some(self.event_fd.try_clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,27 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc, Barrier,
|
||||||
|
};
|
||||||
|
use std::thread;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
|
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
|
||||||
pub struct I8042Device {
|
pub struct I8042Device {
|
||||||
reset_evt: EventFd,
|
reset_evt: EventFd,
|
||||||
|
vcpus_kill_signalled: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl I8042Device {
|
impl I8042Device {
|
||||||
/// Constructs a i8042 device that will signal the given event when the guest requests it.
|
/// Constructs a i8042 device that will signal the given event when the guest requests it.
|
||||||
pub fn new(reset_evt: EventFd) -> I8042Device {
|
pub fn new(reset_evt: EventFd, vcpus_kill_signalled: Arc<AtomicBool>) -> I8042Device {
|
||||||
I8042Device { reset_evt }
|
I8042Device {
|
||||||
|
reset_evt,
|
||||||
|
vcpus_kill_signalled,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +46,13 @@ impl BusDevice for I8042Device {
|
|||||||
if let Err(e) = self.reset_evt.write(1) {
|
if let Err(e) = self.reset_evt.write(1) {
|
||||||
error!("Error triggering i8042 reset event: {}", e);
|
error!("Error triggering i8042 reset event: {}", e);
|
||||||
}
|
}
|
||||||
|
// Spin until we are sure the reset_evt has been handled and that when
|
||||||
|
// we return from the KVM_RUN we will exit rather than re-enter the guest.
|
||||||
|
while !self.vcpus_kill_signalled.load(Ordering::SeqCst) {
|
||||||
|
// This is more effective than thread::yield_now() at
|
||||||
|
// avoiding a priority inversion with the VMM thread
|
||||||
|
thread::sleep(std::time::Duration::from_millis(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -413,10 +413,15 @@ mod tests {
|
|||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
_masked: bool,
|
_masked: bool,
|
||||||
|
_set_gsi: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||||
Some(self.event_fd.try_clone().unwrap())
|
Some(self.event_fd.try_clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -365,9 +365,13 @@ mod tests {
|
|||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
_masked: bool,
|
_masked: bool,
|
||||||
|
_set_gsi: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||||
Some(self.event_fd.try_clone().unwrap())
|
Some(self.event_fd.try_clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,9 +485,13 @@ mod tests {
|
|||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
_masked: bool,
|
_masked: bool,
|
||||||
|
_set_gsi: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||||
Some(self.event_fd.try_clone().unwrap())
|
Some(self.event_fd.try_clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate event_monitor;
|
||||||
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
@@ -19,9 +21,11 @@ pub mod interrupt_controller;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub mod ioapic;
|
pub mod ioapic;
|
||||||
pub mod legacy;
|
pub mod legacy;
|
||||||
|
pub mod pvpanic;
|
||||||
pub mod tpm;
|
pub mod tpm;
|
||||||
|
|
||||||
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
|
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
|
||||||
|
pub use self::pvpanic::{PvPanicDevice, PVPANIC_DEVICE_MMIO_SIZE};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct AcpiNotificationFlags: u8 {
|
pub struct AcpiNotificationFlags: u8 {
|
||||||
|
|||||||
272
devices/src/pvpanic.rs
Normal file
272
devices/src/pvpanic.rs
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
// Copyright © 2023 Tencent Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use pci::{
|
||||||
|
BarReprogrammingParams, PciBarConfiguration, PciBarPrefetchable, PciBarRegionType,
|
||||||
|
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
||||||
|
PCI_CONFIGURATION_ID,
|
||||||
|
};
|
||||||
|
use std::any::Any;
|
||||||
|
use std::result;
|
||||||
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
|
use thiserror::Error;
|
||||||
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
|
use versionize_derive::Versionize;
|
||||||
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
|
use vm_device::{BusDevice, Resource};
|
||||||
|
use vm_memory::{Address, GuestAddress};
|
||||||
|
use vm_migration::{
|
||||||
|
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PVPANIC_VENDOR_ID: u16 = 0x1b36;
|
||||||
|
const PVPANIC_DEVICE_ID: u16 = 0x0011;
|
||||||
|
|
||||||
|
pub const PVPANIC_DEVICE_MMIO_SIZE: u64 = 0x2;
|
||||||
|
|
||||||
|
const PVPANIC_PANICKED: u8 = 1 << 0;
|
||||||
|
const PVPANIC_CRASH_LOADED: u8 = 1 << 1;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum PvPanicError {
|
||||||
|
#[error("Failed creating PvPanicDevice: {0}")]
|
||||||
|
CreatePvPanicDevice(#[source] anyhow::Error),
|
||||||
|
#[error("Failed to retrieve PciConfigurationState: {0}")]
|
||||||
|
RetrievePciConfigurationState(#[source] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum PvPanicSubclass {
|
||||||
|
Other = 0x80,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PciSubclass for PvPanicSubclass {
|
||||||
|
fn get_register_value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A device for handling guest panic event
|
||||||
|
pub struct PvPanicDevice {
|
||||||
|
id: String,
|
||||||
|
events: u8,
|
||||||
|
|
||||||
|
// PCI configuration registers.
|
||||||
|
configuration: PciConfiguration,
|
||||||
|
bar_regions: Vec<PciBarConfiguration>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Versionize)]
|
||||||
|
pub struct PvPanicDeviceState {
|
||||||
|
events: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VersionMapped for PvPanicDeviceState {}
|
||||||
|
|
||||||
|
impl PvPanicDevice {
|
||||||
|
pub fn new(id: String, snapshot: Option<Snapshot>) -> Result<Self, PvPanicError> {
|
||||||
|
let pci_configuration_state =
|
||||||
|
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
|
||||||
|
.map_err(|e| {
|
||||||
|
PvPanicError::RetrievePciConfigurationState(anyhow!(
|
||||||
|
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut configuration = PciConfiguration::new(
|
||||||
|
PVPANIC_VENDOR_ID,
|
||||||
|
PVPANIC_DEVICE_ID,
|
||||||
|
0x1, // modern pci devices
|
||||||
|
PciClassCode::BaseSystemPeripheral,
|
||||||
|
&PvPanicSubclass::Other,
|
||||||
|
None,
|
||||||
|
PciHeaderType::Device,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
pci_configuration_state,
|
||||||
|
);
|
||||||
|
|
||||||
|
let command: [u8; 2] = [0x03, 0x01];
|
||||||
|
configuration.write_config_register(1, 0, &command);
|
||||||
|
|
||||||
|
let state: Option<PvPanicDeviceState> = snapshot
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.to_versioned_state())
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| {
|
||||||
|
PvPanicError::CreatePvPanicDevice(anyhow!(
|
||||||
|
"Failed to get PvPanicDeviceState from Snapshot: {}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
let events = if let Some(state) = state {
|
||||||
|
state.events
|
||||||
|
} else {
|
||||||
|
PVPANIC_PANICKED | PVPANIC_CRASH_LOADED
|
||||||
|
};
|
||||||
|
|
||||||
|
let pvpanic_device = PvPanicDevice {
|
||||||
|
id,
|
||||||
|
events,
|
||||||
|
configuration,
|
||||||
|
bar_regions: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(pvpanic_device)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn event_to_string(&self, event: u8) -> String {
|
||||||
|
if event == PVPANIC_PANICKED {
|
||||||
|
"panic".to_string()
|
||||||
|
} else if event == PVPANIC_CRASH_LOADED {
|
||||||
|
"crash_loaded".to_string()
|
||||||
|
} else {
|
||||||
|
"unknown_event".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> PvPanicDeviceState {
|
||||||
|
PvPanicDeviceState {
|
||||||
|
events: self.events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config_bar_addr(&self) -> u64 {
|
||||||
|
self.configuration.get_bar_addr(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BusDevice for PvPanicDevice {
|
||||||
|
fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
||||||
|
self.read_bar(base, offset, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
||||||
|
let event = self.event_to_string(data[0]);
|
||||||
|
info!("pvpanic got guest event {}", event);
|
||||||
|
event!("guest", "panic", "event", &event);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PciDevice for PvPanicDevice {
|
||||||
|
fn write_config_register(
|
||||||
|
&mut self,
|
||||||
|
reg_idx: usize,
|
||||||
|
offset: u64,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<Arc<Barrier>> {
|
||||||
|
self.configuration
|
||||||
|
.write_config_register(reg_idx, offset, data);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
|
||||||
|
self.configuration.read_reg(reg_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detect_bar_reprogramming(
|
||||||
|
&mut self,
|
||||||
|
reg_idx: usize,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<BarReprogrammingParams> {
|
||||||
|
self.configuration.detect_bar_reprogramming(reg_idx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocate_bars(
|
||||||
|
&mut self,
|
||||||
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
|
_mmio_allocator: &mut AddressAllocator,
|
||||||
|
resources: Option<Vec<Resource>>,
|
||||||
|
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
|
||||||
|
let mut bars = Vec::new();
|
||||||
|
let region_type = PciBarRegionType::Memory32BitRegion;
|
||||||
|
let bar_id = 0;
|
||||||
|
let region_size = PVPANIC_DEVICE_MMIO_SIZE;
|
||||||
|
let restoring = resources.is_some();
|
||||||
|
let bar_addr = allocator
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.allocate_mmio_hole_addresses(None, region_size, None)
|
||||||
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
||||||
|
|
||||||
|
let bar = PciBarConfiguration::default()
|
||||||
|
.set_index(bar_id as usize)
|
||||||
|
.set_address(bar_addr.raw_value())
|
||||||
|
.set_size(region_size)
|
||||||
|
.set_region_type(region_type)
|
||||||
|
.set_prefetchable(PciBarPrefetchable::NotPrefetchable);
|
||||||
|
|
||||||
|
debug!("pvpanic bar address 0x{:x}", bar_addr.0);
|
||||||
|
if !restoring {
|
||||||
|
self.configuration
|
||||||
|
.add_pci_bar(&bar)
|
||||||
|
.map_err(|e| PciDeviceError::IoRegistrationFailed(bar_addr.raw_value(), e))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
bars.push(bar);
|
||||||
|
self.bar_regions = bars.clone();
|
||||||
|
|
||||||
|
Ok(bars)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_bars(
|
||||||
|
&mut self,
|
||||||
|
allocator: &mut SystemAllocator,
|
||||||
|
_mmio_allocator: &mut AddressAllocator,
|
||||||
|
) -> std::result::Result<(), PciDeviceError> {
|
||||||
|
for bar in self.bar_regions.drain(..) {
|
||||||
|
allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_bar(&mut self, old_base: u64, new_base: u64) -> result::Result<(), std::io::Error> {
|
||||||
|
for bar in self.bar_regions.iter_mut() {
|
||||||
|
if bar.addr() == old_base {
|
||||||
|
*bar = bar.set_address(new_base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bar(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
|
||||||
|
data[0] = self.events;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pausable for PvPanicDevice {}
|
||||||
|
|
||||||
|
impl Snapshottable for PvPanicDevice {
|
||||||
|
fn id(&self) -> String {
|
||||||
|
self.id.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||||
|
let mut snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||||
|
|
||||||
|
// Snapshot PciConfiguration
|
||||||
|
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
|
||||||
|
|
||||||
|
Ok(snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transportable for PvPanicDevice {}
|
||||||
|
impl Migratable for PvPanicDevice {}
|
||||||
219
docs/api.md
219
docs/api.md
@@ -1,18 +1,21 @@
|
|||||||
- [Cloud Hypervisor API](#cloud-hypervisor-api)
|
- [Cloud Hypervisor API](#cloud-hypervisor-api)
|
||||||
- [External API](#external-api)
|
- [External API](#external-api)
|
||||||
- [REST API](#rest-api)
|
- [REST API](#rest-api)
|
||||||
- [Location and availability](#location-and-availability)
|
- [REST API Location and availability](#rest-api-location-and-availability)
|
||||||
- [Endpoints](#endpoints)
|
- [REST API Endpoints](#rest-api-endpoints)
|
||||||
- [Virtual Machine Manager (VMM) Actions](#virtual-machine-manager-vmm-actions)
|
- [Virtual Machine Manager (VMM) Actions](#virtual-machine-manager-vmm-actions)
|
||||||
- [Virtual Machine (VM) Actions](#virtual-machine-vm-actions)
|
- [Virtual Machine (VM) Actions](#virtual-machine-vm-actions)
|
||||||
- [REST API Examples](#rest-api-examples)
|
- [REST API Examples](#rest-api-examples)
|
||||||
- [Create a Virtual Machine](#create-a-virtual-machine)
|
- [Create a Virtual Machine](#create-a-virtual-machine)
|
||||||
- [Boot a Virtual Machine](#boot-a-virtual-machine)
|
- [Boot a Virtual Machine](#boot-a-virtual-machine)
|
||||||
- [Dump a Virtual Machine Information](#dump-a-virtual-machine-information)
|
- [Dump a Virtual Machine Information](#dump-a-virtual-machine-information)
|
||||||
- [Reboot a Virtual Machine](#reboot-a-virtual-machine)
|
- [Reboot a Virtual Machine](#reboot-a-virtual-machine)
|
||||||
- [Shut a Virtual Machine Down](#shut-a-virtual-machine-down)
|
- [Shut a Virtual Machine Down](#shut-a-virtual-machine-down)
|
||||||
|
- [D-Bus API](#d-bus-api)
|
||||||
|
- [D-Bus API Location and availability](#d-bus-api-location-and-availability)
|
||||||
|
- [D-Bus API Interface](#d-bus-api-interface)
|
||||||
- [Command Line Interface](#command-line-interface)
|
- [Command Line Interface](#command-line-interface)
|
||||||
- [REST API and CLI Architectural Relationship](#rest-api-and-cli-architectural-relationship)
|
- [REST API, D-Bus API and CLI Architectural Relationship](#rest-api-and-cli-architectural-relationship)
|
||||||
- [Internal API](#internal-api)
|
- [Internal API](#internal-api)
|
||||||
- [Goals and Design](#goals-and-design)
|
- [Goals and Design](#goals-and-design)
|
||||||
- [End to End Example](#end-to-end-example)
|
- [End to End Example](#end-to-end-example)
|
||||||
@@ -21,9 +24,11 @@
|
|||||||
|
|
||||||
The Cloud Hypervisor API is made of 2 distinct interfaces:
|
The Cloud Hypervisor API is made of 2 distinct interfaces:
|
||||||
|
|
||||||
1. **The external API**. This is the user facing API. Users and operators can
|
1. **The External API** This is the user facing API. Users and operators
|
||||||
control and manage Cloud Hypervisor through either a REST API or a Command
|
can control and manage the Cloud Hypervisor through various options
|
||||||
Line Interface (CLI).
|
including a REST API, a Command Line Interface (CLI) or a D-Bus based API,
|
||||||
|
which is not compiled into Cloud Hypervisor by default.
|
||||||
|
|
||||||
1. **The internal API**, based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/)
|
1. **The internal API**, based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/)
|
||||||
module. This API is used internally by the Cloud Hypervisor threads to
|
module. This API is used internally by the Cloud Hypervisor threads to
|
||||||
communicate between each others.
|
communicate between each others.
|
||||||
@@ -40,10 +45,10 @@ API triggers VM and VMM specific actions, and as such it is designed as a
|
|||||||
collection of RPC-style, static methods.
|
collection of RPC-style, static methods.
|
||||||
|
|
||||||
The API is [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md)
|
The API is [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md)
|
||||||
compliant. Please consult the [Cloud Hypervisor API](https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/master/vmm/src/api/openapi/cloud-hypervisor.yaml)
|
compliant. Please consult the [Cloud Hypervisor OpenAPI Document](https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/master/vmm/src/api/openapi/cloud-hypervisor.yaml)
|
||||||
document for more details about the API payloads and responses.
|
for more details about the API payloads and responses.
|
||||||
|
|
||||||
### Location and availability
|
#### REST API Location and availability
|
||||||
|
|
||||||
The REST API is available as soon as the Cloud Hypervisor binary is started,
|
The REST API is available as soon as the Cloud Hypervisor binary is started,
|
||||||
through a local UNIX socket.
|
through a local UNIX socket.
|
||||||
@@ -65,48 +70,55 @@ Cloud Hypervisor Guest
|
|||||||
Disk(s): None
|
Disk(s): None
|
||||||
```
|
```
|
||||||
|
|
||||||
### Endpoints
|
#### REST API Endpoints
|
||||||
|
|
||||||
The Cloud Hypervisor API exposes the following actions through its endpoints:
|
The Cloud Hypervisor API exposes the following actions through its endpoints:
|
||||||
|
|
||||||
#### Virtual Machine Manager (VMM) Actions
|
##### Virtual Machine Manager (VMM) Actions
|
||||||
|
|
||||||
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
||||||
| ----------------------------------- | --------------- | ------------ | -------------------------- | ------------------ |
|
| ----------------------------------- | --------------- | ------------ | -------------------------- | ------------------ |
|
||||||
| Check for the REST API availability | `/vmm.ping` | N/A | `/schemas/VmmPingResponse` | N/A |
|
| Check for the REST API availability | `/vmm.ping` | N/A | `/schemas/VmmPingResponse` | N/A |
|
||||||
| Shut the VMM down | `/vmm.shutdown` | N/A | N/A | The VMM is running |
|
| Shut the VMM down | `/vmm.shutdown` | N/A | N/A | The VMM is running |
|
||||||
|
|
||||||
#### Virtual Machine (VM) Actions
|
##### Virtual Machine (VM) Actions
|
||||||
|
|
||||||
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
||||||
| ---------------------------------- | --------------------- | --------------------------- | ------------------------ | -------------------------------- |
|
| ---------------------------------- | ----------------------- | ------------------------------- | ------------------------ | ------------------------------------------------------ |
|
||||||
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
|
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
|
||||||
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
|
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
|
||||||
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
|
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
|
||||||
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
|
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
|
||||||
| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted |
|
| Reboot the VM | `/vm.reboot` | 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 |
|
| 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 |
|
| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused |
|
||||||
| Perform a coredump of the VM | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused |
|
| Perform a coredump of the VM* | `/vm.coredump` | `/schemas/VmCoredumpData` | 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 |
|
| 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 |
|
||||||
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
|
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
|
||||||
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||||
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||||
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||||
| 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 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 |
|
||||||
|
| Prepare to receive a migration | `/vm.receive-migration` | `/schemas/ReceiveMigrationData` | N/A | N/A |
|
||||||
|
| Start to send migration to target | `/vm.send-migration` | `/schemas/SendMigrationData` | N/A | The VM is booted and (shared mem or hugepages enabled) |
|
||||||
|
|
||||||
### REST API Examples
|
* The `vmcoredump` action is available exclusively for the `x86_64`
|
||||||
|
architecture and can be executed only when the `guest_debug` feature is
|
||||||
|
enabled. Without this feature, the corresponding [REST API](#rest-api) or
|
||||||
|
[D-Bus API](#d-bus-api) endpoints are not available.
|
||||||
|
|
||||||
|
#### REST API Examples
|
||||||
|
|
||||||
For the following set of examples, we assume Cloud Hypervisor is started with
|
For the following set of examples, we assume Cloud Hypervisor is started with
|
||||||
the REST API available at `/tmp/cloud-hypervisor.sock`:
|
the REST API available at `/tmp/cloud-hypervisor.sock`:
|
||||||
@@ -122,7 +134,7 @@ Cloud Hypervisor Guest
|
|||||||
Disk(s): None
|
Disk(s): None
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Create a Virtual Machine
|
##### Create a Virtual Machine
|
||||||
|
|
||||||
We want to create a virtual machine with the following characteristics:
|
We want to create a virtual machine with the following characteristics:
|
||||||
|
|
||||||
@@ -150,7 +162,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
|||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Boot a Virtual Machine
|
##### Boot a Virtual Machine
|
||||||
|
|
||||||
Once the VM is created, we can boot it:
|
Once the VM is created, we can boot it:
|
||||||
|
|
||||||
@@ -160,7 +172,7 @@ Once the VM is created, we can boot it:
|
|||||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.boot'
|
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.boot'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Dump a Virtual Machine Information
|
##### Dump a Virtual Machine Information
|
||||||
|
|
||||||
We can fetch information about any VM, as soon as it's created:
|
We can fetch information about any VM, as soon as it's created:
|
||||||
|
|
||||||
@@ -172,7 +184,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
|||||||
-H 'Accept: application/json'
|
-H 'Accept: application/json'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Reboot a Virtual Machine
|
##### Reboot a Virtual Machine
|
||||||
|
|
||||||
We can reboot a VM that's already booted:
|
We can reboot a VM that's already booted:
|
||||||
|
|
||||||
@@ -182,7 +194,7 @@ We can reboot a VM that's already booted:
|
|||||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.reboot'
|
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.reboot'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Shut a Virtual Machine Down
|
##### Shut a Virtual Machine Down
|
||||||
|
|
||||||
Once booted, we can shut a VM down from the REST API:
|
Once booted, we can shut a VM down from the REST API:
|
||||||
|
|
||||||
@@ -192,6 +204,50 @@ Once booted, we can shut a VM down from the REST API:
|
|||||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.shutdown'
|
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.shutdown'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### D-Bus API
|
||||||
|
|
||||||
|
Cloud Hypervisor offers a D-Bus API as an alternative to its REST API. As of
|
||||||
|
writing this document, the D-Bus API mirrors the functionality of the REST
|
||||||
|
API and shares the same set of endpoints, meaning that it supports every call
|
||||||
|
that is supported by the REST API and can be a drop-in replacement since it
|
||||||
|
also consumes/produces JSON.
|
||||||
|
|
||||||
|
#### D-Bus API Location and availability
|
||||||
|
|
||||||
|
This feature is not compiled into Cloud Hypervisor by default. Users who
|
||||||
|
wish to use the D-Bus API, must explicitly enable it with the `dbus_api`
|
||||||
|
feature flag when compiling Cloud Hypervisor.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ./scripts/dev_cli.sh build --release --libc musl -- --features dbus_api
|
||||||
|
```
|
||||||
|
|
||||||
|
Once this feature is enabled, it can be configured with the following
|
||||||
|
CLI options:
|
||||||
|
|
||||||
|
```
|
||||||
|
--dbus-service-name
|
||||||
|
well known name of the service
|
||||||
|
--dbus-object-path
|
||||||
|
object path to serve the dbus interface
|
||||||
|
--dbus-system-bus use the system bus instead of a session bus
|
||||||
|
```
|
||||||
|
|
||||||
|
Example invocation:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ./cloud-hypervisor --dbus-service-name "org.cloudhypervisor.DBusApi" \
|
||||||
|
--dbus-object-path "/org/cloudhypervisor/DBusApi"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start serving a service with the name `org.cloudhypervisor.DBusApi1`
|
||||||
|
which in turn can be used to control and manage Cloud Hypervisor.
|
||||||
|
|
||||||
|
#### D-Bus API Interface
|
||||||
|
|
||||||
|
Please refer to the [REST API](#rest-api) documentation. As previously
|
||||||
|
mentioned, the D-Bus API currently mirrors the behaviour of the REST API.
|
||||||
|
|
||||||
### Command Line Interface
|
### Command Line Interface
|
||||||
|
|
||||||
The Cloud Hypervisor Command Line Interface (CLI) can only be used for launching
|
The Cloud Hypervisor Command Line Interface (CLI) can only be used for launching
|
||||||
@@ -199,33 +255,41 @@ the Cloud Hypervisor binary, i.e. it can not be used for controlling the VMM or
|
|||||||
the launched VM once they're up and running.
|
the launched VM once they're up and running.
|
||||||
|
|
||||||
If you want to inspect the VMM, or control the VM after launching Cloud
|
If you want to inspect the VMM, or control the VM after launching Cloud
|
||||||
Hypervisor from the CLI, you must use the [REST API](#rest-api).
|
Hypervisor from the CLI, you must use either the [REST API](#rest-api)
|
||||||
|
or the [D-Bus API](#d-bus-api).
|
||||||
|
|
||||||
From the CLI, one can either:
|
From the CLI, one can:
|
||||||
|
|
||||||
1. Create and boot a complete virtual machine by using the CLI options to build
|
1. Create and boot a complete virtual machine by using the CLI options to build
|
||||||
the VM config. Run `cloud-hypervisor --help` for a complete list of CLI
|
the VM config. Run `cloud-hypervisor --help` for a complete list of CLI
|
||||||
options. As soon as the `cloud-hypervisor` binary is launched, the
|
options. As soon as the `cloud-hypervisor` binary is launched, contrary
|
||||||
[REST API](#rest-api) is available for controlling and managing the VM.
|
to the [D-Bus API](#d-bus-api), the [REST API](#rest-api) is available
|
||||||
1. Start the [REST API](#rest-api) server only, by not passing any VM
|
for controlling and managing the VM. The [D-Bus API](#d-bus-api) doesn't start
|
||||||
configuration options. The VM can then be asynchronously created and booted
|
automatically and needs to be explicitly configured in order to be run.
|
||||||
by sending HTTP commands to the [REST API](#rest-api). Check the
|
1. Start either the REST API, D-Bus API or both simultaneously without passing
|
||||||
[REST API examples](#rest-api-examples) section for more details.
|
any VM configuration options. The VM can then be asynchronously created and
|
||||||
|
booted by calling API methods of choice. It should be noted that one external
|
||||||
|
API does not exclude another; it is possible to have both the REST and D-Bus
|
||||||
|
APIs running simultaneously.
|
||||||
|
|
||||||
### REST API and CLI Architectural Relationship
|
### REST API, D-Bus API and CLI Architectural Relationship
|
||||||
|
|
||||||
The REST API and the CLI both rely on a common, [internal API](#internal-api).
|
The REST API, D-Bus API and the CLI all rely on a common, [internal API](#internal-api).
|
||||||
|
|
||||||
The CLI options are parsed by the
|
The CLI options are parsed by the
|
||||||
[argh crate](https://docs.rs/argh/latest/argh/) and then translated into
|
[argh crate](https://docs.rs/argh/latest/argh/) and then translated into
|
||||||
[internal API](#internal-api) commands.
|
[internal API](#internal-api) commands.
|
||||||
|
|
||||||
The REST API is processed by an HTTP thread using the
|
The REST API is processed by an HTTP thread using the
|
||||||
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
|
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/micro-http)
|
||||||
crate. As with the CLI, the HTTP requests eventually get translated into
|
crate. As with the CLI, the HTTP requests eventually get translated into
|
||||||
[internal API](#internal-api) commands.
|
[internal API](#internal-api) commands.
|
||||||
|
|
||||||
As a summary, the REST API and the CLI are essentially frontends for the
|
The D-Bus API is implemented using the [zbus](https://github.com/dbus2/zbus)
|
||||||
|
crate and runs in its own thread. Whenever it needs to call the [internal API](#internal-api),
|
||||||
|
the [blocking](https://github.com/smol-rs/blocking) crate is used perform the call in zbus' async context.
|
||||||
|
|
||||||
|
As a summary, the REST API, the D-Bus API and the CLI are essentially frontends for the
|
||||||
[internal API](#internal-api):
|
[internal API](#internal-api):
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -236,11 +300,11 @@ As a summary, the REST API and the CLI are essentially frontends for the
|
|||||||
| +------------------+ |
|
| +------------------+ |
|
||||||
| | +------------------------+
|
| | +------------------------+
|
||||||
| | | |
|
| | | |
|
||||||
+------------+ | | | |
|
+------------+ | +----------+ | | |
|
||||||
| | | | | +--------------+ |
|
| | | D-Bus API | | | | +--------------+ |
|
||||||
| User +---------+ +------> | Internal API | |
|
| User +---------+----------->+ zbus +--------------+------> | Internal API | |
|
||||||
| | | | | +--------------+ |
|
| | | | | | | +--------------+ |
|
||||||
+------------+ | | | |
|
+------------+ | +----------+ | | |
|
||||||
| | | |
|
| | | |
|
||||||
| | +------------------------+
|
| | +------------------------+
|
||||||
| +----------+ | VMM
|
| +----------+ | VMM
|
||||||
@@ -255,22 +319,23 @@ As a summary, the REST API and the CLI are essentially frontends for the
|
|||||||
## Internal API
|
## Internal API
|
||||||
|
|
||||||
The Cloud Hypervisor internal API, as its name suggests, is used internally
|
The Cloud Hypervisor internal API, as its name suggests, is used internally
|
||||||
by the different Cloud Hypervisor threads (VMM, HTTP, control loop, etc) to
|
by the different Cloud Hypervisor threads (VMM, HTTP, D-Bus, control loop,
|
||||||
send commands and responses to each others.
|
etc) to send commands and responses to each others.
|
||||||
|
|
||||||
It is based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/),
|
It is based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/),
|
||||||
and the single consumer (a.k.a. the API receiver) is the Cloud Hypervisor
|
and the single consumer (a.k.a. the API receiver) is the Cloud Hypervisor
|
||||||
control loop.
|
control loop.
|
||||||
|
|
||||||
API producers are the HTTP thread handling the [REST API](#rest-api) and the
|
API producers are the HTTP thread handling the [REST API](#rest-api), the
|
||||||
main thread that initially parses the [CLI](#command-line-interface).
|
D-Bus thread handling the [D-Bus API](#d-bus-api) and the main thread that
|
||||||
|
initially parses the [CLI](#command-line-interface).
|
||||||
|
|
||||||
### Goals and Design
|
### Goals and Design
|
||||||
|
|
||||||
The internal API is designed for controlling, managing and inspecting a Cloud
|
The internal API is designed for controlling, managing and inspecting a Cloud
|
||||||
Hypervisor VMM and its guest. It is a backend for handling external, user
|
Hypervisor VMM and its guest. It is a backend for handling external, user
|
||||||
visible requests through either the [REST API](#rest-api) or the
|
visible requests through the [REST API](#rest-api), the [D-Bus API](#d-bus-api)
|
||||||
[CLI](#command-line-interface) interfaces.
|
or the [CLI](#command-line-interface) interfaces.
|
||||||
|
|
||||||
The API follows a command-response scheme that closely maps the [REST API](#rest-api).
|
The API follows a command-response scheme that closely maps the [REST API](#rest-api).
|
||||||
Any command must be replied to with a response.
|
Any command must be replied to with a response.
|
||||||
@@ -379,5 +444,5 @@ APIs work together, let's look at a complete VM creation flow, from the
|
|||||||
```
|
```
|
||||||
1. The Cloud Hypervisor HTTP thread sends the formed HTTP response back to the
|
1. The Cloud Hypervisor HTTP thread sends the formed HTTP response back to the
|
||||||
user. This is abstracted by the
|
user. This is abstracted by the
|
||||||
[micro_http](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
|
[micro_http](https://github.com/firecracker-microvm/micro-http)
|
||||||
crate.
|
crate.
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ Number Start End Size File system Name Flags
|
|||||||
|
|
||||||
### Create a macvtap interface
|
### Create a macvtap interface
|
||||||
|
|
||||||
Rely on the following [documentation](docs/macvtap-bridge.md) to set up a
|
Rely on the following [documentation](macvtap-bridge.md) to set up a
|
||||||
macvtap interface to provide your VM with proper connectivity.
|
macvtap interface to provide your VM with proper connectivity.
|
||||||
|
|
||||||
### Boot the image
|
### Boot the image
|
||||||
|
|||||||
@@ -266,11 +266,8 @@ _Example_
|
|||||||
|
|
||||||
### `file`
|
### `file`
|
||||||
|
|
||||||
Path to the file backing the memory zone. This can be either a file or a
|
Path to the file backing the memory zone. The file will be opened and used as
|
||||||
directory. In case of a file, it will be opened and used as the backing file
|
the backing file for the `mmap(2)` operation.
|
||||||
for the `mmap(2)` operation. In case of a directory, a temporary file with no
|
|
||||||
hard link on the filesystem will be created. This file will be used as the
|
|
||||||
backing file for the `mmap(2)` operation.
|
|
||||||
|
|
||||||
This option can be particularly useful when trying to back a part of the guest
|
This option can be particularly useful when trying to back a part of the guest
|
||||||
RAM with a well known file. In the context of the snapshot/restore feature, and
|
RAM with a well known file. In the context of the snapshot/restore feature, and
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ authors = ["The Cloud Hypervisor Authors"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
flume = "0.10.14"
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.96"
|
||||||
|
|||||||
@@ -7,33 +7,11 @@ use serde::Serialize;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
static mut MONITOR: Option<(File, Instant)> = None;
|
static mut MONITOR: Option<MonitorHandle> = None;
|
||||||
|
|
||||||
/// This function must only be called once from the main process before any threads
|
|
||||||
/// are created to avoid race conditions
|
|
||||||
pub fn set_monitor(file: File) -> Result<(), std::io::Error> {
|
|
||||||
// SAFETY: there is only one caller of this function, so MONITOR is written to only once
|
|
||||||
assert!(unsafe { MONITOR.is_none() });
|
|
||||||
let fd = file.as_raw_fd();
|
|
||||||
// SAFETY: FFI call to configure the fd
|
|
||||||
let ret = unsafe {
|
|
||||||
let mut flags = libc::fcntl(fd, libc::F_GETFL);
|
|
||||||
flags |= libc::O_NONBLOCK;
|
|
||||||
libc::fcntl(fd, libc::F_SETFL, flags)
|
|
||||||
};
|
|
||||||
if ret < 0 {
|
|
||||||
return Err(std::io::Error::last_os_error());
|
|
||||||
}
|
|
||||||
// SAFETY: MONITOR is None. Nobody else can hold a reference to it.
|
|
||||||
unsafe {
|
|
||||||
MONITOR = Some((file, Instant::now()));
|
|
||||||
};
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Event<'a> {
|
struct Event<'a> {
|
||||||
@@ -43,19 +21,71 @@ struct Event<'a> {
|
|||||||
properties: Option<&'a HashMap<Cow<'a, str>, Cow<'a, str>>>,
|
properties: Option<&'a HashMap<Cow<'a, str>, Cow<'a, str>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Monitor {
|
||||||
|
pub rx: flume::Receiver<String>,
|
||||||
|
pub file: File,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MonitorHandle {
|
||||||
|
tx: flume::Sender<String>,
|
||||||
|
start: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_file_nonblocking(file: &File) -> io::Result<()> {
|
||||||
|
let fd = file.as_raw_fd();
|
||||||
|
|
||||||
|
// SAFETY: FFI call to configure the fd
|
||||||
|
let ret = unsafe {
|
||||||
|
let mut flags = libc::fcntl(fd, libc::F_GETFL);
|
||||||
|
flags |= libc::O_NONBLOCK;
|
||||||
|
libc::fcntl(fd, libc::F_SETFL, flags)
|
||||||
|
};
|
||||||
|
|
||||||
|
if ret < 0 {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function must only be called once from the main thread before any threads
|
||||||
|
/// are created to avoid race conditions.
|
||||||
|
pub fn set_monitor(file: File) -> io::Result<Monitor> {
|
||||||
|
// SAFETY: there is only one caller of this function, so MONITOR is written to only once
|
||||||
|
assert!(unsafe { MONITOR.is_none() });
|
||||||
|
|
||||||
|
set_file_nonblocking(&file)?;
|
||||||
|
let (tx, rx) = flume::unbounded();
|
||||||
|
let monitor = Monitor { rx, file };
|
||||||
|
|
||||||
|
// SAFETY: MONITOR is None. Nobody else can hold a reference to it.
|
||||||
|
unsafe {
|
||||||
|
MONITOR = Some(MonitorHandle {
|
||||||
|
tx,
|
||||||
|
start: Instant::now(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(monitor)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>, Cow<str>>>) {
|
pub fn event_log(source: &str, event: &str, properties: Option<&HashMap<Cow<str>, Cow<str>>>) {
|
||||||
// SAFETY: MONITOR is always in a valid state (None or Some).
|
// SAFETY: `MONITOR` is always in a valid state (None or Some), because it
|
||||||
if let Some((file, start)) = unsafe { MONITOR.as_ref() } {
|
// is set only once before any threads are spawned, and it's not mutated
|
||||||
let e = Event {
|
// afterwards. This function only creates immutable references to `MONITOR`.
|
||||||
timestamp: start.elapsed(),
|
// Because `MONITOR.tx` is `Sync`, it's safe to share `MONITOR` across
|
||||||
|
// threads, making this function thread-safe.
|
||||||
|
if let Some(monitor_handle) = unsafe { MONITOR.as_ref() } {
|
||||||
|
let event = Event {
|
||||||
|
timestamp: monitor_handle.start.elapsed(),
|
||||||
source,
|
source,
|
||||||
event,
|
event,
|
||||||
properties,
|
properties,
|
||||||
};
|
};
|
||||||
serde_json::to_writer_pretty(file, &e).ok();
|
|
||||||
|
|
||||||
let mut file = file;
|
if let Ok(event) = serde_json::to_string_pretty(&event) {
|
||||||
file.write_all(b"\n\n").ok();
|
monitor_handle.tx.send(event).ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,5 +109,4 @@ macro_rules! event {
|
|||||||
$crate::event_log($source, $event, Some(&properties))
|
$crate::event_log($source, $event, Some(&properties))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
476
fuzz/Cargo.lock
generated
476
fuzz/Cargo.lock
generated
@@ -5,16 +5,16 @@ version = 3
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "acpi_tables"
|
name = "acpi_tables"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#4fd38dd5f746730ec5ae848dafcf8c2f50a13fc3"
|
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#05a609136387cc1cc9b499cee4320020325c263f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vm-memory",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.69"
|
version = "1.0.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -25,9 +25,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
version = "1.2.3"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad"
|
checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
@@ -76,7 +76,7 @@ dependencies = [
|
|||||||
"argh_shared",
|
"argh_shared",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -85,6 +85,12 @@ version = "0.1.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
|
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "1.3.3"
|
version = "1.3.3"
|
||||||
@@ -101,25 +107,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block_util"
|
name = "bitflags"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"crc32c",
|
||||||
"io-uring",
|
"io-uring",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"qcow",
|
"remain",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"uuid",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhdx",
|
"virtio-bindings",
|
||||||
"virtio-bindings 0.2.0",
|
|
||||||
"virtio-queue",
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@@ -128,11 +148,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.79"
|
version = "1.0.82"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -143,7 +164,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "29.0.0"
|
version = "33.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -169,7 +190,7 @@ dependencies = [
|
|||||||
name = "cloud-hypervisor-fuzz"
|
name = "cloud-hypervisor-fuzz"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block_util",
|
"block",
|
||||||
"cloud-hypervisor",
|
"cloud-hypervisor",
|
||||||
"devices",
|
"devices",
|
||||||
"epoll",
|
"epoll",
|
||||||
@@ -179,9 +200,7 @@ dependencies = [
|
|||||||
"micro_http",
|
"micro_http",
|
||||||
"net_util",
|
"net_util",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"qcow",
|
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"vhdx",
|
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
"virtio-queue",
|
"virtio-queue",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
@@ -193,9 +212,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e"
|
checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -208,9 +227,9 @@ checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.14.3"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
|
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"darling_macro",
|
"darling_macro",
|
||||||
@@ -218,27 +237,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_core"
|
name = "darling_core"
|
||||||
version = "0.14.3"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
|
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.14.3"
|
version = "0.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
|
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -248,15 +267,18 @@ dependencies = [
|
|||||||
"acpi_tables",
|
"acpi_tables",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arch",
|
"arch",
|
||||||
"bitflags",
|
"bitflags 2.3.3",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"event_monitor",
|
||||||
"hypervisor",
|
"hypervisor",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
"pci",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tpm",
|
"tpm",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-migration",
|
"vm-migration",
|
||||||
@@ -265,11 +287,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "epoll"
|
name = "epoll"
|
||||||
version = "4.3.1"
|
version = "4.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0"
|
checksum = "74351c3392ea1ff6cd2628e0042d268ac2371cb613252ff383b6dfa50d22fa79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.3.3",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -277,6 +299,7 @@ dependencies = [
|
|||||||
name = "event_monitor"
|
name = "event_monitor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"flume",
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -288,6 +311,19 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
|
checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flume"
|
||||||
|
version = "0.10.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"nanorand",
|
||||||
|
"pin-project",
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@@ -295,14 +331,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "futures-core"
|
||||||
version = "0.2.8"
|
version = "0.3.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -311,7 +361,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"iced-x86",
|
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
"kvm-ioctls",
|
"kvm-ioctls",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -324,15 +373,6 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iced-x86"
|
|
||||||
version = "1.18.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1dd04b950d75b3498320253b17fb92745b2cc79ead8814aede2f7c1bab858bec"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -341,29 +381,38 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-uring"
|
name = "io-uring"
|
||||||
version = "0.5.13"
|
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 = "dd1e1a01cfb924fd8c5c43b6827965db394f5a3a16c599ce03452266e1cf984c"
|
checksum = "8b7b36074613a723279637061b40db993208908a94f10ccb14436ce735bc0f57"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.5"
|
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 = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-bindings"
|
name = "kvm-bindings"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -385,17 +434,11 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.147"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -410,22 +453,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-loader"
|
name = "linux-loader"
|
||||||
version = "0.8.1"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9259ddbfbb52cc918f6bbc60390004ddd0228cf1d85f402009ff2b3d95de83f"
|
checksum = "8d3adb7b28e189741eca3b1a4a27de0bf15e0907c9d4b0c74bd2d7d84ef72e08"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "lock_api"
|
||||||
version = "0.4.17"
|
version = "0.4.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -435,6 +485,15 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanorand"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net_gen"
|
name = "net_gen"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -456,7 +515,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"virtio-bindings 0.2.0",
|
"virtio-bindings",
|
||||||
"virtio-queue",
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
@@ -465,9 +524,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.1"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
@@ -497,30 +556,39 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "pin-project"
|
||||||
version = "1.0.51"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-internal"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.23",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.66"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "qcow"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"remain",
|
|
||||||
"vmm-sys-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -536,13 +604,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remain"
|
name = "remain"
|
||||||
version = "0.2.6"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5704e2cda92fd54202f05430725317ba0ea7d0c96b246ca0a92e45177127ba3b"
|
checksum = "bce3a7139d2ee67d07538ee5dba997364fbc243e7e7143e96eb830c74bfaa082"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -556,9 +624,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.12"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "seccompiler"
|
name = "seccompiler"
|
||||||
@@ -571,35 +645,35 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.16"
|
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 = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.168"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
checksum = "d614f89548720367ded108b3c843be93f3a341e22d5674ca0dd5cd57f34926af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.152"
|
version = "1.0.168"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
checksum = "d4fe589678c688e44177da4f27152ee2d190757271dc7f1d5b6b9f68d869d641"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.93"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -608,9 +682,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with"
|
name = "serde_with"
|
||||||
version = "2.2.0"
|
version = "3.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c"
|
checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_with_macros",
|
"serde_with_macros",
|
||||||
@@ -618,14 +692,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_with_macros"
|
name = "serde_with_macros"
|
||||||
version = "2.2.0"
|
version = "3.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e"
|
checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -634,9 +708,9 @@ version = "0.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.15"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -653,9 +727,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.10.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
@@ -665,9 +748,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.108"
|
version = "1.0.109"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14"
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -676,22 +770,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.38"
|
version = "1.0.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.38"
|
version = "1.0.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -720,24 +814,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.6"
|
version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.3.0"
|
version = "1.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "versionize"
|
name = "versionize"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6e2495726cf917e7ba7ec8bf0f0fceab543dd38d0a4195ed6bef331e38a290f"
|
checksum = "dca4b7062e7e6d685901e815c35f9671e059de97c1c0905eeff8592f3fff442f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"crc64",
|
"crc64",
|
||||||
@@ -745,7 +839,7 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"syn",
|
"syn 1.0.109",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -753,17 +847,17 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "versionize_derive"
|
name = "versionize_derive"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#ae35ef7a3ddabd3371ab8ac0193a383aff6e4b1b"
|
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#e502b1d4aabab342386f0c53780d49f21a6a1df6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -771,7 +865,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
|
source = "git+https://github.com/rust-vmm/vfio?branch=main#89f8e77dd1a2829197ecde65b686bafcc8a1def4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
@@ -787,9 +881,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio_user"
|
name = "vfio_user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#afbbd5722885e961ce12baea12efe01d52ce14b0"
|
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#eef6bec4d421f08ed1688fe67c5ea33aabbf5069"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -801,26 +895,13 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vhdx"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"crc32c",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"remain",
|
|
||||||
"thiserror",
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9b791c5b0717a0558888a4cf7240cea836f39a99cb342e12ce633dcaa078072"
|
checksum = "84f81f436bca4541f4d33172e1202882c9d437db34ed17fc6d84c8ff2bde21f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -828,15 +909,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-bindings"
|
name = "virtio-bindings"
|
||||||
version = "0.1.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b"
|
checksum = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "virtio-bindings"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b9084faf91b9aa9676ae2cac8f1432df2839d9566e6f19f29dbc13a8b831dff"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-devices"
|
name = "virtio-devices"
|
||||||
@@ -844,11 +919,10 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"block_util",
|
"block",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
"io-uring",
|
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"net_gen",
|
"net_gen",
|
||||||
@@ -863,7 +937,7 @@ dependencies = [
|
|||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
"virtio-bindings 0.2.0",
|
"virtio-bindings",
|
||||||
"virtio-queue",
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
@@ -875,12 +949,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-queue"
|
name = "virtio-queue"
|
||||||
version = "0.7.1"
|
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 = "3ba81e2bcc21c0d2fc5e6683e79367e26ad219197423a498df801d79d5ba77bd"
|
checksum = "91aebb1df33db33cbf04d4c2445e4f78d0b0c8e65acfd16a4ee95ef63ca252f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"virtio-bindings 0.1.0",
|
"virtio-bindings",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -914,9 +988,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "688a70366615b45575a424d9c665561c1b5ab2224d494f706b6a6812911a827c"
|
checksum = "9d6ea57fe00f9086c59eeeb68e102dd611686bc3c28520fa465996d4d4bdce07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -953,8 +1027,8 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"arch",
|
"arch",
|
||||||
"bitflags",
|
"bitflags 2.3.3",
|
||||||
"block_util",
|
"block",
|
||||||
"devices",
|
"devices",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
@@ -967,7 +1041,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"option_parser",
|
"option_parser",
|
||||||
"pci",
|
"pci",
|
||||||
"qcow",
|
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -980,7 +1053,6 @@ dependencies = [
|
|||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vfio-ioctls",
|
"vfio-ioctls",
|
||||||
"vfio_user",
|
"vfio_user",
|
||||||
"vhdx",
|
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
"virtio-queue",
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
@@ -989,6 +1061,7 @@ dependencies = [
|
|||||||
"vm-migration",
|
"vm-migration",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -997,7 +1070,7 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46"
|
checksum = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
@@ -1009,6 +1082,60 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.87"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.87"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.23",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.87"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.87"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.23",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.87"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -1030,3 +1157,24 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||||||
version = "0.4.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 = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3b9c234616391070b0b173963ebc65a9195068e7ed3731c6edac2ec45ebe106"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f7f3a471f98d0a61c34322fbbfd10c384b07687f680d4119813713f72308d91"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.23",
|
||||||
|
]
|
||||||
|
|||||||
@@ -9,23 +9,21 @@ edition = "2021"
|
|||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_util = { path = "../block_util" }
|
block = { path = "../block" }
|
||||||
devices = { path = "../devices" }
|
devices = { path = "../devices" }
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
libc = "0.2.138"
|
libc = "0.2.147"
|
||||||
libfuzzer-sys = "0.4.6"
|
libfuzzer-sys = "0.4.6"
|
||||||
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.9.0", features = ["elf", "bzimage", "pe"] }
|
||||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
||||||
net_util = { path = "../net_util" }
|
net_util = { path = "../net_util" }
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.18.0"
|
||||||
qcow = { path = "../qcow" }
|
|
||||||
seccompiler = "0.3.0"
|
seccompiler = "0.3.0"
|
||||||
vhdx = { path = "../vhdx" }
|
|
||||||
virtio-devices = { path = "../virtio-devices" }
|
virtio-devices = { path = "../virtio-devices" }
|
||||||
virtio-queue = "0.7.1"
|
virtio-queue = "0.8.0"
|
||||||
vmm = { path = "../vmm" }
|
vmm = { path = "../vmm" }
|
||||||
vmm-sys-util = "0.11.1"
|
vmm-sys-util = "0.11.1"
|
||||||
vm-memory = "0.10.0"
|
vm-memory = "0.11.0"
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use block_util::{async_io::DiskFile, raw_sync::RawFileDiskSync};
|
use block::{async_io::DiskFile, raw_sync::RawFileDiskSync};
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
use seccompiler::SeccompAction;
|
use seccompiler::SeccompAction;
|
||||||
use std::ffi;
|
use std::ffi;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
use devices::legacy::Cmos;
|
use devices::legacy::Cmos;
|
||||||
use libc::EFD_NONBLOCK;
|
use libc::EFD_NONBLOCK;
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::Arc;
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
@@ -25,6 +27,7 @@ fuzz_target!(|bytes| {
|
|||||||
u64::from_le_bytes(below_4g),
|
u64::from_le_bytes(below_4g),
|
||||||
u64::from_le_bytes(above_4g),
|
u64::from_le_bytes(above_4g),
|
||||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut i = 16;
|
let mut i = 16;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
use qcow::{QcowFile, RawFile};
|
use block::qcow::{QcowFile, RawFile};
|
||||||
use std::ffi;
|
use std::ffi;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
|
||||||
|
|||||||
@@ -59,9 +59,13 @@ impl InterruptSourceGroup for TestInterrupt {
|
|||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
_masked: bool,
|
_masked: bool,
|
||||||
|
_set_gsi: bool,
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn set_gsi(&self) -> Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||||
Some(self.event_fd.try_clone().unwrap())
|
Some(self.event_fd.try_clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::ffi;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||||
use std::os::unix::io::{FromRawFd, RawFd};
|
use std::os::unix::io::{FromRawFd, RawFd};
|
||||||
use vhdx::vhdx::Vhdx;
|
use block::vhdx::Vhdx;
|
||||||
|
|
||||||
// Populate the corpus directory with a test file:
|
// Populate the corpus directory with a test file:
|
||||||
// truncate -s 16M /tmp/source
|
// truncate -s 16M /tmp/source
|
||||||
|
|||||||
@@ -6,28 +6,29 @@ edition = "2021"
|
|||||||
license = "Apache-2.0 OR BSD-3-Clause"
|
license = "Apache-2.0 OR BSD-3-Clause"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
kvm = ["kvm-ioctls", "kvm-bindings"]
|
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
|
||||||
mshv = ["mshv-ioctls", "mshv-bindings"]
|
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"]
|
||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.71"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
kvm-ioctls = { version = "0.13.0", optional = true }
|
kvm-ioctls = { version = "0.13.0", optional = true }
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
||||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
||||||
serde_with = { version = "2.1.0", default-features = false, features = ["macros"] }
|
serde_with = { version = "3.0.0", default-features = false, features = ["macros"] }
|
||||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic"] }
|
||||||
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||||
version = "1.18.0"
|
optional = true
|
||||||
|
version = "1.19.0"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
|
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,36 @@ impl<T: CpuStateManager> InstructionHandler<T> for Movzx_r64_rm16 {
|
|||||||
movzx!(u64, u16);
|
movzx!(u64, u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Mov_moffs16_AX;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs16_AX {
|
||||||
|
movzx!(u16, u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mov_AX_moffs16;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_AX_moffs16 {
|
||||||
|
movzx!(u16, u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mov_moffs32_EAX;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs32_EAX {
|
||||||
|
movzx!(u32, u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mov_EAX_moffs32;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_EAX_moffs32 {
|
||||||
|
movzx!(u32, u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mov_moffs64_RAX;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_moffs64_RAX {
|
||||||
|
movzx!(u64, u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mov_RAX_moffs64;
|
||||||
|
impl<T: CpuStateManager> InstructionHandler<T> for Mov_RAX_moffs64 {
|
||||||
|
movzx!(u64, u64);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(unused_mut)]
|
#![allow(unused_mut)]
|
||||||
@@ -617,4 +647,123 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(eax, value as u64);
|
assert_eq!(eax, value as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// movabs ax, ds:0x1337
|
||||||
|
// movabs eax, ds:0x1337
|
||||||
|
// movabs rax, ds:0x1337
|
||||||
|
fn test_mov_memoff_ax() {
|
||||||
|
let test_inputs: [(Register, &[u8]); 3] = [
|
||||||
|
(Register::AX, &[0x66, 0xa1]),
|
||||||
|
(Register::EAX, &[0xa1]),
|
||||||
|
(Register::RAX, &[0x48, 0xa1]),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Constructs the instruction with the provided inputs and emulates it.
|
||||||
|
fn helper(register: Register, instruction_prefix: &[u8]) {
|
||||||
|
let mem_addr: u64 = 0x1337;
|
||||||
|
let mem_value: u64 = 0x13371337deadbeef;
|
||||||
|
let ip: u64 = 0x1000;
|
||||||
|
let cpu_id = 0;
|
||||||
|
|
||||||
|
let mut instruction_bytes = Vec::new();
|
||||||
|
// instruction prefix with specified register
|
||||||
|
instruction_bytes.extend(instruction_prefix);
|
||||||
|
// 64-bit memory operand
|
||||||
|
instruction_bytes.extend([
|
||||||
|
mem_addr.to_le_bytes()[0],
|
||||||
|
mem_addr.to_le_bytes()[1],
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
let memory: [u8; 8] = mem_value.to_le_bytes();
|
||||||
|
let mut vmm = MockVmm::new(ip, vec![], Some((mem_addr, &memory)));
|
||||||
|
assert!(vmm.emulate_first_insn(cpu_id, &instruction_bytes).is_ok());
|
||||||
|
|
||||||
|
let ax: u64 = vmm.cpu_state(cpu_id).unwrap().read_reg(register).unwrap();
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::AX => {
|
||||||
|
assert_eq!(ax as u16, mem_value as u16);
|
||||||
|
}
|
||||||
|
Register::EAX => {
|
||||||
|
assert_eq!(ax as u32, mem_value as u32);
|
||||||
|
}
|
||||||
|
Register::RAX => {
|
||||||
|
assert_eq!(ax, mem_value);
|
||||||
|
}
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (register, instruction_prefix) in test_inputs {
|
||||||
|
helper(register, instruction_prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// movabs ds:0x1337, ax
|
||||||
|
// movabs ds:0x1337, eax
|
||||||
|
// movabs ds:0x1337, rax
|
||||||
|
fn test_mov_ax_memoff() {
|
||||||
|
let test_inputs: [(Register, &[u8]); 3] = [
|
||||||
|
(Register::AX, &[0x66, 0xa3]),
|
||||||
|
(Register::EAX, &[0xa3]),
|
||||||
|
(Register::RAX, &[0x48, 0xa3]),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Constructs the instruction with the provided inputs and emulates it.
|
||||||
|
fn helper(register: Register, instruction_prefix: &[u8]) {
|
||||||
|
let mem_addr: u64 = 0x1337;
|
||||||
|
let ax: u64 = 0x13371337deadbeef;
|
||||||
|
let ip: u64 = 0x1000;
|
||||||
|
let cpu_id = 0;
|
||||||
|
|
||||||
|
let mut instruction_bytes = Vec::new();
|
||||||
|
// instruction prefix with specified register
|
||||||
|
instruction_bytes.extend(instruction_prefix);
|
||||||
|
// 64-bit memory operand
|
||||||
|
instruction_bytes.extend([
|
||||||
|
mem_addr.to_le_bytes()[0],
|
||||||
|
mem_addr.to_le_bytes()[1],
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
let mut vmm = MockVmm::new(ip, vec![(Register::RAX, ax)], None);
|
||||||
|
assert!(vmm.emulate_first_insn(cpu_id, &instruction_bytes).is_ok());
|
||||||
|
|
||||||
|
match register {
|
||||||
|
Register::AX => {
|
||||||
|
let mut memory: [u8; 2] = [0; 2];
|
||||||
|
vmm.read_memory(mem_addr, &mut memory).unwrap();
|
||||||
|
assert_eq!(u16::from_le_bytes(memory), ax as u16);
|
||||||
|
}
|
||||||
|
Register::EAX => {
|
||||||
|
let mut memory: [u8; 4] = [0; 4];
|
||||||
|
vmm.read_memory(mem_addr, &mut memory).unwrap();
|
||||||
|
assert_eq!(u32::from_le_bytes(memory), ax as u32);
|
||||||
|
}
|
||||||
|
Register::RAX => {
|
||||||
|
let mut memory: [u8; 8] = [0; 8];
|
||||||
|
vmm.read_memory(mem_addr, &mut memory).unwrap();
|
||||||
|
assert_eq!(u64::from_le_bytes(memory), ax);
|
||||||
|
}
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (register, instruction_prefix) in test_inputs {
|
||||||
|
helper(register, instruction_prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -524,6 +524,13 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
|||||||
(mov, Movzx_r64_rm8),
|
(mov, Movzx_r64_rm8),
|
||||||
(mov, Movzx_r32_rm16),
|
(mov, Movzx_r32_rm16),
|
||||||
(mov, Movzx_r64_rm16),
|
(mov, Movzx_r64_rm16),
|
||||||
|
// MOV MOFFS
|
||||||
|
(mov, Mov_moffs16_AX),
|
||||||
|
(mov, Mov_AX_moffs16),
|
||||||
|
(mov, Mov_moffs32_EAX),
|
||||||
|
(mov, Mov_EAX_moffs32),
|
||||||
|
(mov, Mov_moffs64_RAX),
|
||||||
|
(mov, Mov_RAX_moffs64),
|
||||||
// MOVS
|
// MOVS
|
||||||
(movs, Movsd_m32_m32),
|
(movs, Movsd_m32_m32),
|
||||||
(movs, Movsw_m16_m16),
|
(movs, Movsw_m16_m16),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
// Copyright © 2020, Microsoft Corporation
|
// Copyright © 2020, Microsoft Corporation
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
pub mod emulator;
|
pub mod emulator;
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
@@ -26,7 +27,6 @@ pub const MTRR_MEM_TYPE_WB: u64 = 0x6;
|
|||||||
pub const NUM_IOAPIC_PINS: usize = 24;
|
pub const NUM_IOAPIC_PINS: usize = 24;
|
||||||
|
|
||||||
// X86 Exceptions
|
// X86 Exceptions
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Exception {
|
pub enum Exception {
|
||||||
DE = 0, // Divide Error
|
DE = 0, // Divide Error
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ use crate::MpState;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub enum CpuVendor {
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
Intel,
|
||||||
|
AMD,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
///
|
///
|
||||||
/// Enum for CPU error
|
/// Enum for CPU error
|
||||||
|
|||||||
@@ -9,10 +9,14 @@
|
|||||||
//
|
//
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86::CpuIdEntry;
|
use crate::arch::x86::CpuIdEntry;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::cpu::CpuVendor;
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
use crate::kvm::TdxCapabilities;
|
use crate::kvm::TdxCapabilities;
|
||||||
use crate::vm::Vm;
|
use crate::vm::Vm;
|
||||||
use crate::HypervisorType;
|
use crate::HypervisorType;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use std::arch::x86_64;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
@@ -75,6 +79,11 @@ pub enum HypervisorError {
|
|||||||
///
|
///
|
||||||
#[error("Failed to set partition property:{0}")]
|
#[error("Failed to set partition property:{0}")]
|
||||||
SetPartitionProperty(#[source] anyhow::Error),
|
SetPartitionProperty(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
|
/// Running on an unsupported CPU
|
||||||
|
///
|
||||||
|
#[error("Unsupported CPU:{0}")]
|
||||||
|
UnsupportedCpu(#[source] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -133,4 +142,30 @@ pub trait Hypervisor: Send + Sync {
|
|||||||
fn get_guest_debug_hw_bps(&self) -> usize {
|
fn get_guest_debug_hw_bps(&self) -> usize {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get maximum number of vCPUs
|
||||||
|
fn get_max_vcpus(&self) -> u32;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
///
|
||||||
|
/// Determine CPU vendor
|
||||||
|
///
|
||||||
|
fn get_cpu_vendor(&self) -> CpuVendor {
|
||||||
|
// SAFETY: call cpuid with valid leaves
|
||||||
|
unsafe {
|
||||||
|
let leaf = x86_64::__cpuid(0x0);
|
||||||
|
|
||||||
|
if leaf.ebx == 0x756e_6547 && leaf.ecx == 0x6c65_746e && leaf.edx == 0x4965_6e69 {
|
||||||
|
// Vendor string GenuineIntel
|
||||||
|
CpuVendor::Intel
|
||||||
|
} else if leaf.ebx == 0x6874_7541 && leaf.ecx == 0x444d_4163 && leaf.edx == 0x6974_6e65
|
||||||
|
{
|
||||||
|
// Vendor string AuthenticAMD
|
||||||
|
CpuVendor::AMD
|
||||||
|
} else {
|
||||||
|
// Not known yet, the corresponding manufacturer manual should contain the
|
||||||
|
// necesssary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String
|
||||||
|
CpuVendor::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,7 +243,6 @@ impl KvmGicV3Its {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Method to initialize the GIC device
|
/// Method to initialize the GIC device
|
||||||
#[allow(clippy::new_ret_no_self)]
|
|
||||||
pub fn new(vm: &dyn Vm, config: VgicConfig) -> Result<KvmGicV3Its> {
|
pub fn new(vm: &dyn Vm, config: VgicConfig) -> Result<KvmGicV3Its> {
|
||||||
// This is inside KVM module
|
// This is inside KVM module
|
||||||
let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?");
|
let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?");
|
||||||
|
|||||||
@@ -330,21 +330,22 @@ impl KvmVm {
|
|||||||
Ok(VfioDeviceFd::new_from_kvm(device_fd))
|
Ok(VfioDeviceFd::new_from_kvm(device_fd))
|
||||||
}
|
}
|
||||||
/// Checks if a particular `Cap` is available.
|
/// Checks if a particular `Cap` is available.
|
||||||
fn check_extension(&self, c: Cap) -> bool {
|
pub fn check_extension(&self, c: Cap) -> bool {
|
||||||
self.fd.check_extension(c)
|
self.fd.check_extension(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Implementation of Vm trait for KVM
|
/// Implementation of Vm trait for KVM
|
||||||
/// Example:
|
|
||||||
/// #[cfg(feature = "kvm")]
|
|
||||||
/// extern crate hypervisor
|
|
||||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
|
||||||
/// vm.set/get().unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let kvm = KvmHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(kvm);
|
||||||
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
|
/// ```
|
||||||
impl vm::Vm for KvmVm {
|
impl vm::Vm for KvmVm {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
@@ -917,13 +918,16 @@ impl KvmHypervisor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Implementation of Hypervisor trait for KVM
|
/// Implementation of Hypervisor trait for KVM
|
||||||
/// Example:
|
|
||||||
/// #[cfg(feature = "kvm")]
|
|
||||||
/// extern crate hypervisor
|
|
||||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let kvm = KvmHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(kvm);
|
||||||
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
|
/// ```
|
||||||
impl hypervisor::Hypervisor for KvmHypervisor {
|
impl hypervisor::Hypervisor for KvmHypervisor {
|
||||||
///
|
///
|
||||||
/// Returns the type of the hypervisor
|
/// Returns the type of the hypervisor
|
||||||
@@ -932,13 +936,15 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
HypervisorType::Kvm
|
HypervisorType::Kvm
|
||||||
}
|
}
|
||||||
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object
|
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object
|
||||||
/// Example
|
|
||||||
/// # extern crate hypervisor;
|
|
||||||
/// # use hypervisor::KvmHypervisor;
|
|
||||||
/// use hypervisor::KvmVm;
|
|
||||||
/// let hypervisor = KvmHypervisor::new().unwrap();
|
|
||||||
/// let vm = hypervisor.create_vm_with_type(KvmVmType::LegacyVm).unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
|
/// use hypervisor::kvm::KvmVm;
|
||||||
|
/// let hypervisor = KvmHypervisor::new().unwrap();
|
||||||
|
/// let vm = hypervisor.create_vm_with_type(0).unwrap();
|
||||||
|
/// ```
|
||||||
fn create_vm_with_type(&self, vm_type: u64) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
fn create_vm_with_type(&self, vm_type: u64) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||||
let fd: VmFd;
|
let fd: VmFd;
|
||||||
loop {
|
loop {
|
||||||
@@ -992,13 +998,15 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a KVM vm object and return the object as Vm trait object
|
/// Create a KVM vm object and return the object as Vm trait object
|
||||||
/// Example
|
|
||||||
/// # extern crate hypervisor;
|
|
||||||
/// # use hypervisor::KvmHypervisor;
|
|
||||||
/// use hypervisor::KvmVm;
|
|
||||||
/// let hypervisor = KvmHypervisor::new().unwrap();
|
|
||||||
/// let vm = hypervisor.create_vm().unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
|
/// use hypervisor::kvm::KvmVm;
|
||||||
|
/// let hypervisor = KvmHypervisor::new().unwrap();
|
||||||
|
/// let vm = hypervisor.create_vm().unwrap();
|
||||||
|
/// ```
|
||||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut vm_type: u64 = 0; // Create with default platform type
|
let mut vm_type: u64 = 0; // Create with default platform type
|
||||||
@@ -1076,6 +1084,11 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||||||
self.kvm.get_guest_debug_hw_bps() as usize
|
self.kvm.get_guest_debug_hw_bps() as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get maximum number of vCPUs
|
||||||
|
fn get_max_vcpus(&self) -> u32 {
|
||||||
|
self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Vcpu struct for KVM
|
/// Vcpu struct for KVM
|
||||||
pub struct KvmVcpu {
|
pub struct KvmVcpu {
|
||||||
@@ -1087,15 +1100,17 @@ pub struct KvmVcpu {
|
|||||||
hyperv_synic: AtomicBool,
|
hyperv_synic: AtomicBool,
|
||||||
}
|
}
|
||||||
/// Implementation of Vcpu trait for KVM
|
/// Implementation of Vcpu trait for KVM
|
||||||
/// Example:
|
///
|
||||||
/// #[cfg(feature = "kvm")]
|
/// # Examples
|
||||||
/// extern crate hypervisor
|
///
|
||||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
/// ```
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let kvm = KvmHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(kvm);
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||||
/// vcpu.get/set().unwrap()
|
/// ```
|
||||||
///
|
|
||||||
impl cpu::Vcpu for KvmVcpu {
|
impl cpu::Vcpu for KvmVcpu {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
@@ -1797,11 +1812,10 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate hypervisor;
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
/// # use hypervisor::KvmHypervisor;
|
|
||||||
/// # use std::sync::Arc;
|
/// # use std::sync::Arc;
|
||||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
/// let kvm = KvmHypervisor::new().unwrap();
|
||||||
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
/// let hv = Arc::new(kvm);
|
||||||
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
||||||
/// vm.enable_split_irq().unwrap();
|
/// vm.enable_split_irq().unwrap();
|
||||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||||
@@ -1969,11 +1983,10 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate hypervisor;
|
/// # use hypervisor::kvm::KvmHypervisor;
|
||||||
/// # use hypervisor::KvmHypervisor;
|
|
||||||
/// # use std::sync::Arc;
|
/// # use std::sync::Arc;
|
||||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
/// let kvm = KvmHypervisor::new().unwrap();
|
||||||
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
/// let hv = Arc::new(kvm);
|
||||||
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
||||||
/// vm.enable_split_irq().unwrap();
|
/// vm.enable_split_irq().unwrap();
|
||||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ pub mod kvm;
|
|||||||
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
#[cfg(all(feature = "mshv", target_arch = "x86_64"))]
|
||||||
pub mod mshv;
|
pub mod mshv;
|
||||||
|
|
||||||
/// Hypevisor related module
|
/// Hypervisor related module
|
||||||
mod hypervisor;
|
mod hypervisor;
|
||||||
|
|
||||||
/// Vm related module
|
/// Vm related module
|
||||||
@@ -48,9 +48,11 @@ mod cpu;
|
|||||||
/// Device related module
|
/// Device related module
|
||||||
mod device;
|
mod device;
|
||||||
|
|
||||||
|
pub use crate::hypervisor::{Hypervisor, HypervisorError};
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub use cpu::CpuVendor;
|
||||||
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
|
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
|
||||||
pub use device::HypervisorDeviceError;
|
pub use device::HypervisorDeviceError;
|
||||||
pub use hypervisor::{Hypervisor, HypervisorError};
|
|
||||||
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
|
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
|
||||||
pub use kvm::{aarch64, GicState};
|
pub use kvm::{aarch64, GicState};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ use std::fs::File;
|
|||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86::{
|
use crate::arch::x86::{CpuIdEntry, FpuState, MsrEntry};
|
||||||
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4;
|
const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4;
|
||||||
const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8;
|
const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8;
|
||||||
@@ -195,13 +193,16 @@ impl MshvHypervisor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Implementation of Hypervisor trait for Mshv
|
/// Implementation of Hypervisor trait for Mshv
|
||||||
/// Example:
|
|
||||||
/// #[cfg(feature = "mshv")]
|
|
||||||
/// extern crate hypervisor
|
|
||||||
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
|
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::mshv::MshvHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let mshv = MshvHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(mshv);
|
||||||
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
|
/// ```
|
||||||
impl hypervisor::Hypervisor for MshvHypervisor {
|
impl hypervisor::Hypervisor for MshvHypervisor {
|
||||||
///
|
///
|
||||||
/// Returns the type of the hypervisor
|
/// Returns the type of the hypervisor
|
||||||
@@ -210,13 +211,16 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
HypervisorType::Mshv
|
HypervisorType::Mshv
|
||||||
}
|
}
|
||||||
/// Create a mshv vm object and return the object as Vm trait object
|
/// Create a mshv vm object and return the object as Vm trait object
|
||||||
/// Example
|
|
||||||
/// # extern crate hypervisor;
|
|
||||||
/// # use hypervisor::MshvHypervisor;
|
|
||||||
/// use hypervisor::MshvVm;
|
|
||||||
/// let hypervisor = MshvHypervisor::new().unwrap();
|
|
||||||
/// let vm = hypervisor.create_vm().unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # extern crate hypervisor;
|
||||||
|
/// # use hypervisor::mshv::MshvHypervisor;
|
||||||
|
/// use hypervisor::mshv::MshvVm;
|
||||||
|
/// let hypervisor = MshvHypervisor::new().unwrap();
|
||||||
|
/// let vm = hypervisor.create_vm().unwrap();
|
||||||
|
/// ```
|
||||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||||
let fd: VmFd;
|
let fd: VmFd;
|
||||||
loop {
|
loop {
|
||||||
@@ -273,6 +277,13 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
|||||||
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
|
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get maximum number of vCPUs
|
||||||
|
fn get_max_vcpus(&self) -> u32 {
|
||||||
|
// TODO: Using HV_MAXIMUM_PROCESSORS would be better
|
||||||
|
// but the ioctl API is limited to u8
|
||||||
|
256
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vcpu struct for Microsoft Hypervisor
|
/// Vcpu struct for Microsoft Hypervisor
|
||||||
@@ -285,21 +296,23 @@ pub struct MshvVcpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of Vcpu trait for Microsoft Hypervisor
|
/// Implementation of Vcpu trait for Microsoft Hypervisor
|
||||||
/// Example:
|
|
||||||
/// #[cfg(feature = "mshv")]
|
|
||||||
/// extern crate hypervisor
|
|
||||||
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
|
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
|
||||||
/// let vcpu = vm.create_vcpu(0).unwrap();
|
|
||||||
/// vcpu.get/set().unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use hypervisor::mshv::MshvHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let mshv = MshvHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(mshv);
|
||||||
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
|
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||||
|
/// ```
|
||||||
impl cpu::Vcpu for MshvVcpu {
|
impl cpu::Vcpu for MshvVcpu {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Returns the vCPU general purpose registers.
|
/// Returns the vCPU general purpose registers.
|
||||||
///
|
///
|
||||||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
fn get_regs(&self) -> cpu::Result<crate::arch::x86::StandardRegisters> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.fd
|
.fd
|
||||||
.get_regs()
|
.get_regs()
|
||||||
@@ -310,7 +323,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// Sets the vCPU general purpose registers.
|
/// Sets the vCPU general purpose registers.
|
||||||
///
|
///
|
||||||
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
|
fn set_regs(&self, regs: &crate::arch::x86::StandardRegisters) -> cpu::Result<()> {
|
||||||
let regs = (*regs).into();
|
let regs = (*regs).into();
|
||||||
self.fd
|
self.fd
|
||||||
.set_regs(®s)
|
.set_regs(®s)
|
||||||
@@ -320,7 +333,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// Returns the vCPU special registers.
|
/// Returns the vCPU special registers.
|
||||||
///
|
///
|
||||||
fn get_sregs(&self) -> cpu::Result<SpecialRegisters> {
|
fn get_sregs(&self) -> cpu::Result<crate::arch::x86::SpecialRegisters> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.fd
|
.fd
|
||||||
.get_sregs()
|
.get_sregs()
|
||||||
@@ -331,7 +344,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// Sets the vCPU special registers.
|
/// Sets the vCPU special registers.
|
||||||
///
|
///
|
||||||
fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> {
|
fn set_sregs(&self, sregs: &crate::arch::x86::SpecialRegisters) -> cpu::Result<()> {
|
||||||
let sregs = (*sregs).into();
|
let sregs = (*sregs).into();
|
||||||
self.fd
|
self.fd
|
||||||
.set_sregs(&sregs)
|
.set_sregs(&sregs)
|
||||||
@@ -446,10 +459,10 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
/* Advance RIP and update RAX */
|
/* Advance RIP and update RAX */
|
||||||
let arr_reg_name_value = [
|
let arr_reg_name_value = [
|
||||||
(
|
(
|
||||||
hv_x64_register_name_HV_X64_REGISTER_RIP,
|
hv_register_name_HV_X64_REGISTER_RIP,
|
||||||
info.header.rip + insn_len,
|
info.header.rip + insn_len,
|
||||||
),
|
),
|
||||||
(hv_x64_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
(hv_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||||
];
|
];
|
||||||
set_registers_64!(self.fd, arr_reg_name_value)
|
set_registers_64!(self.fd, arr_reg_name_value)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
||||||
@@ -495,10 +508,10 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
/* Advance RIP and update RAX */
|
/* Advance RIP and update RAX */
|
||||||
let arr_reg_name_value = [
|
let arr_reg_name_value = [
|
||||||
(
|
(
|
||||||
hv_x64_register_name_HV_X64_REGISTER_RIP,
|
hv_register_name_HV_X64_REGISTER_RIP,
|
||||||
info.header.rip + insn_len,
|
info.header.rip + insn_len,
|
||||||
),
|
),
|
||||||
(hv_x64_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
(hv_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||||
];
|
];
|
||||||
set_registers_64!(self.fd, arr_reg_name_value)
|
set_registers_64!(self.fd, arr_reg_name_value)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
||||||
@@ -568,8 +581,14 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// X86 specific call to setup the CPUID registers.
|
/// X86 specific call to setup the CPUID registers.
|
||||||
///
|
///
|
||||||
fn set_cpuid2(&self, _cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
|
fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
|
||||||
Ok(())
|
let cpuid: Vec<mshv_bindings::hv_cpuid_entry> = cpuid.iter().map(|e| (*e).into()).collect();
|
||||||
|
let mshv_cpuid = <CpuId>::from_entries(&cpuid)
|
||||||
|
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
|
||||||
|
|
||||||
|
self.fd
|
||||||
|
.register_intercept_result_cpuid(&mshv_cpuid)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
@@ -582,7 +601,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
|
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
|
||||||
///
|
///
|
||||||
fn get_lapic(&self) -> cpu::Result<LapicState> {
|
fn get_lapic(&self) -> cpu::Result<crate::arch::x86::LapicState> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.fd
|
.fd
|
||||||
.get_lapic()
|
.get_lapic()
|
||||||
@@ -593,7 +612,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
///
|
///
|
||||||
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
|
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
|
||||||
///
|
///
|
||||||
fn set_lapic(&self, lapic: &LapicState) -> cpu::Result<()> {
|
fn set_lapic(&self, lapic: &crate::arch::x86::LapicState) -> cpu::Result<()> {
|
||||||
let lapic: mshv_bindings::LapicState = (*lapic).clone().into();
|
let lapic: mshv_bindings::LapicState = (*lapic).clone().into();
|
||||||
self.fd
|
self.fd
|
||||||
.set_lapic(&lapic)
|
.set_lapic(&lapic)
|
||||||
@@ -917,15 +936,17 @@ impl MshvVm {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// Implementation of Vm trait for Mshv
|
/// Implementation of Vm trait for Mshv
|
||||||
/// Example:
|
|
||||||
/// #[cfg(feature = "mshv")]
|
|
||||||
/// # extern crate hypervisor;
|
|
||||||
/// # use hypervisor::MshvHypervisor;
|
|
||||||
/// let mshv = MshvHypervisor::new().unwrap();
|
|
||||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
|
||||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
|
||||||
/// vm.set/get().unwrap()
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # extern crate hypervisor;
|
||||||
|
/// # use hypervisor::mshv::MshvHypervisor;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
|
/// let mshv = MshvHypervisor::new().unwrap();
|
||||||
|
/// let hypervisor = Arc::new(mshv);
|
||||||
|
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||||
|
/// ```
|
||||||
impl vm::Vm for MshvVm {
|
impl vm::Vm for MshvVm {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
|
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
|
||||||
|
#[allow(clippy::missing_safety_doc)]
|
||||||
impl<T> __IncompleteArrayField<T> {
|
impl<T> __IncompleteArrayField<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
|
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
|
||||||
|
#[allow(clippy::missing_safety_doc)]
|
||||||
impl<T> __IncompleteArrayField<T> {
|
impl<T> __IncompleteArrayField<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#![allow(clippy::all)]
|
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
@@ -28,10 +27,12 @@ pub mod inn;
|
|||||||
// generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust
|
// generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust
|
||||||
// --constified-enum '*' --with-derive-default
|
// --constified-enum '*' --with-derive-default
|
||||||
pub mod sockios;
|
pub mod sockios;
|
||||||
pub use if_tun::*;
|
pub use if_tun::{
|
||||||
pub use iff::*;
|
sock_fprog, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_TAP, IFF_VNET_HDR, TUN_F_CSUM, TUN_F_TSO4,
|
||||||
pub use inn::*;
|
TUN_F_TSO6, TUN_F_TSO_ECN, TUN_F_UFO,
|
||||||
pub use sockios::*;
|
};
|
||||||
|
pub use iff::{ifreq, net_device_flags_IFF_UP, setsockopt, sockaddr, AF_INET};
|
||||||
|
pub use inn::sockaddr_in;
|
||||||
|
|
||||||
pub const TUNTAP: ::std::os::raw::c_uint = 84;
|
pub const TUNTAP: ::std::os::raw::c_uint = 84;
|
||||||
|
|
||||||
|
|||||||
@@ -5,24 +5,24 @@ authors = ["The Chromium OS Authors"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.3"
|
||||||
getrandom = "0.2.8"
|
getrandom = "0.2.10"
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
net_gen = { path = "../net_gen" }
|
net_gen = { path = "../net_gen" }
|
||||||
rate_limiter = { path = "../rate_limiter" }
|
rate_limiter = { path = "../rate_limiter" }
|
||||||
serde = "1.0.151"
|
serde = "1.0.164"
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
versionize = "0.1.9"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = "0.2.0"
|
virtio-bindings = "0.2.0"
|
||||||
virtio-queue = "0.7.0"
|
virtio-queue = "0.8.0"
|
||||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.18.0"
|
||||||
pnet = "0.33.0"
|
pnet = "0.33.0"
|
||||||
pnet_datalink = "0.33.0"
|
pnet_datalink = "0.33.0"
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.96"
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ impl TxVirtio {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
libc::writev(
|
libc::writev(
|
||||||
tap.as_raw_fd() as libc::c_int,
|
tap.as_raw_fd() as libc::c_int,
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
iovecs.as_ptr(),
|
||||||
iovecs.len() as libc::c_int,
|
iovecs.len() as libc::c_int,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -226,7 +226,7 @@ impl RxVirtio {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
libc::readv(
|
libc::readv(
|
||||||
tap.as_raw_fd() as libc::c_int,
|
tap.as_raw_fd() as libc::c_int,
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
iovecs.as_ptr(),
|
||||||
iovecs.len() as libc::c_int,
|
iovecs.len() as libc::c_int,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ kvm = ["vfio-ioctls/kvm"]
|
|||||||
mshv = ["vfio-ioctls/mshv"]
|
mshv = ["vfio-ioctls/mshv"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.71"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
||||||
@@ -20,11 +20,11 @@ vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
|||||||
vmm-sys-util = "0.11.0"
|
vmm-sys-util = "0.11.0"
|
||||||
libc = "0.2.139"
|
libc = "0.2.139"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
serde = { version = "1.0.151", features = ["derive"] }
|
serde = { version = "1.0.164", features = ["derive"] }
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
versionize = "0.1.9"
|
versionize = "0.1.10"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
vm-memory = { version = "0.11.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
|
|||||||
@@ -452,10 +452,9 @@ impl From<PciBarType> for PciBarRegionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::from_over_into)]
|
impl From<PciBarRegionType> for PciBarType {
|
||||||
impl Into<PciBarType> for PciBarRegionType {
|
fn from(val: PciBarRegionType) -> Self {
|
||||||
fn into(self) -> PciBarType {
|
match val {
|
||||||
match self {
|
|
||||||
PciBarRegionType::IoRegion => PciBarType::Io,
|
PciBarRegionType::IoRegion => PciBarType::Io,
|
||||||
PciBarRegionType::Memory32BitRegion => PciBarType::Mmio32,
|
PciBarRegionType::Memory32BitRegion => PciBarType::Mmio32,
|
||||||
PciBarRegionType::Memory64BitRegion => PciBarType::Mmio64,
|
PciBarRegionType::Memory64BitRegion => PciBarType::Mmio64,
|
||||||
@@ -469,10 +468,9 @@ pub enum PciBarPrefetchable {
|
|||||||
Prefetchable = 0x08,
|
Prefetchable = 0x08,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::from_over_into)]
|
impl From<PciBarPrefetchable> for bool {
|
||||||
impl Into<bool> for PciBarPrefetchable {
|
fn from(val: PciBarPrefetchable) -> Self {
|
||||||
fn into(self) -> bool {
|
match val {
|
||||||
match self {
|
|
||||||
PciBarPrefetchable::NotPrefetchable => false,
|
PciBarPrefetchable::NotPrefetchable => false,
|
||||||
PciBarPrefetchable::Prefetchable => true,
|
PciBarPrefetchable::Prefetchable => true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,10 +205,15 @@ impl MsiConfig {
|
|||||||
idx as InterruptIndex,
|
idx as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
state.cap.vector_masked(idx),
|
state.cap.vector_masked(idx),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.map_err(Error::UpdateInterruptRoute)?;
|
.map_err(Error::UpdateInterruptRoute)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interrupt_source_group
|
||||||
|
.set_gsi()
|
||||||
|
.map_err(Error::EnableInterruptRoute)?;
|
||||||
|
|
||||||
interrupt_source_group
|
interrupt_source_group
|
||||||
.enable()
|
.enable()
|
||||||
.map_err(Error::EnableInterruptRoute)?;
|
.map_err(Error::EnableInterruptRoute)?;
|
||||||
@@ -262,6 +267,7 @@ impl MsiConfig {
|
|||||||
idx as InterruptIndex,
|
idx as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
self.cap.vector_masked(idx),
|
self.cap.vector_masked(idx),
|
||||||
|
true,
|
||||||
) {
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ impl MsixConfig {
|
|||||||
idx as InterruptIndex,
|
idx as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
state.masked,
|
state.masked,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.map_err(Error::UpdateInterruptRoute)?;
|
.map_err(Error::UpdateInterruptRoute)?;
|
||||||
|
|
||||||
@@ -182,6 +183,7 @@ impl MsixConfig {
|
|||||||
idx as InterruptIndex,
|
idx as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
table_entry.masked(),
|
table_entry.masked(),
|
||||||
|
true,
|
||||||
) {
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
@@ -320,6 +322,7 @@ impl MsixConfig {
|
|||||||
index as InterruptIndex,
|
index as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
table_entry.masked(),
|
table_entry.masked(),
|
||||||
|
true,
|
||||||
) {
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
error!("Failed updating vector: {:?}", e);
|
||||||
}
|
}
|
||||||
@@ -511,6 +514,16 @@ impl MsixCap {
|
|||||||
self.pba & 0xffff_fff8
|
self.pba & 0xffff_fff8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn table_set_offset(&mut self, addr: u32) {
|
||||||
|
self.table &= 0x7;
|
||||||
|
self.table += addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pba_set_offset(&mut self, addr: u32) {
|
||||||
|
self.pba &= 0x7;
|
||||||
|
self.pba += addr;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn table_bir(&self) -> u32 {
|
pub fn table_bir(&self) -> u32 {
|
||||||
self.table & 0x7
|
self.table & 0x7
|
||||||
}
|
}
|
||||||
|
|||||||
103
pci/src/vfio.rs
103
pci/src/vfio.rs
@@ -14,6 +14,7 @@ use crate::{
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use hypervisor::HypervisorVmError;
|
use hypervisor::HypervisorVmError;
|
||||||
|
use libc::{sysconf, _SC_PAGESIZE};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -27,6 +28,9 @@ use vfio_bindings::bindings::vfio::*;
|
|||||||
use vfio_ioctls::{
|
use vfio_ioctls::{
|
||||||
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
|
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
|
||||||
};
|
};
|
||||||
|
use vm_allocator::page_size::{
|
||||||
|
align_page_size_down, align_page_size_up, is_4k_aligned, is_4k_multiple, is_page_size_aligned,
|
||||||
|
};
|
||||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
||||||
@@ -498,6 +502,33 @@ impl VfioCommon {
|
|||||||
Ok(vfio_common)
|
Ok(vfio_common)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In case msix table offset is not page size aligned, we need do some fixup to achive it.
|
||||||
|
/// Becuse we don't want the MMIO RW region and trap region overlap each other.
|
||||||
|
fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
|
||||||
|
if let Some(msix) = self.interrupt.msix.as_mut() {
|
||||||
|
let msix_cap = &mut msix.cap;
|
||||||
|
|
||||||
|
// Suppose table_bir equals to pba_bir here. Am I right?
|
||||||
|
let (table_offset, table_size) = msix_cap.table_range();
|
||||||
|
if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id {
|
||||||
|
return region_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (pba_offset, pba_size) = msix_cap.pba_range();
|
||||||
|
let msix_sz = align_page_size_up(table_size + pba_size);
|
||||||
|
// Expand region to hold RW and trap region which both page size aligned
|
||||||
|
let size = std::cmp::max(region_size * 2, msix_sz * 2);
|
||||||
|
// let table starts from the middle of the region
|
||||||
|
msix_cap.table_set_offset((size / 2) as u32);
|
||||||
|
msix_cap.pba_set_offset((size / 2 + pba_offset - table_offset) as u32);
|
||||||
|
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
// MSI-X not supported for this device
|
||||||
|
region_size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn allocate_bars(
|
pub(crate) fn allocate_bars(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocator: &Arc<Mutex<SystemAllocator>>,
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
@@ -661,9 +692,16 @@ impl VfioCommon {
|
|||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
||||||
}
|
}
|
||||||
PciBarRegionType::Memory64BitRegion => {
|
PciBarRegionType::Memory64BitRegion => {
|
||||||
// BAR allocation must be naturally aligned
|
// We need do some fixup to keep MMIO RW region and msix cap region page size
|
||||||
|
// aligned.
|
||||||
|
region_size = self.fixup_msix_region(bar_id, region_size);
|
||||||
mmio_allocator
|
mmio_allocator
|
||||||
.allocate(restored_bar_addr, region_size, Some(region_size))
|
.allocate(
|
||||||
|
restored_bar_addr,
|
||||||
|
region_size,
|
||||||
|
// SAFETY: FFI call. Trivially safe.
|
||||||
|
Some(unsafe { sysconf(_SC_PAGESIZE) as GuestUsize }),
|
||||||
|
)
|
||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -800,6 +838,23 @@ impl VfioCommon {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_msix_cap_idx(&self) -> Option<usize> {
|
||||||
|
let mut cap_next = self
|
||||||
|
.vfio_wrapper
|
||||||
|
.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
|
||||||
|
|
||||||
|
while cap_next != 0 {
|
||||||
|
let cap_id = self.vfio_wrapper.read_config_byte(cap_next.into());
|
||||||
|
if PciCapabilityId::from(cap_id) == PciCapabilityId::MsiX {
|
||||||
|
return Some(cap_next as usize);
|
||||||
|
} else {
|
||||||
|
cap_next = self.vfio_wrapper.read_config_byte((cap_next + 1).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_capabilities(&mut self, bdf: PciBdf) {
|
pub(crate) fn parse_capabilities(&mut self, bdf: PciBdf) {
|
||||||
let mut cap_next = self
|
let mut cap_next = self
|
||||||
.vfio_wrapper
|
.vfio_wrapper
|
||||||
@@ -1154,6 +1209,15 @@ impl VfioCommon {
|
|||||||
return self.configuration.read_reg(reg_idx);
|
return self.configuration.read_reg(reg_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(id) = self.get_msix_cap_idx() {
|
||||||
|
let msix = self.interrupt.msix.as_mut().unwrap();
|
||||||
|
if reg_idx * 4 == id + 4 {
|
||||||
|
return msix.cap.table;
|
||||||
|
} else if reg_idx * 4 == id + 8 {
|
||||||
|
return msix.cap.pba;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Since we don't support passing multi-functions devices, we should
|
// Since we don't support passing multi-functions devices, we should
|
||||||
// mask the multi-function bit, bit 7 of the Header Type byte on the
|
// mask the multi-function bit, bit 7 of the Header Type byte on the
|
||||||
// register 3.
|
// register 3.
|
||||||
@@ -1316,18 +1380,6 @@ impl VfioPciDevice {
|
|||||||
self.iommu_attached
|
self.iommu_attached
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_4k(address: u64) -> u64 {
|
|
||||||
(address + 0xfff) & 0xffff_ffff_ffff_f000
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_4k_aligned(address: u64) -> bool {
|
|
||||||
(address & 0xfff) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_4k_multiple(size: u64) -> bool {
|
|
||||||
(size & 0xfff) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_sparse_areas(
|
fn generate_sparse_areas(
|
||||||
caps: &[VfioRegionInfoCap],
|
caps: &[VfioRegionInfoCap],
|
||||||
region_index: u32,
|
region_index: u32,
|
||||||
@@ -1339,14 +1391,14 @@ impl VfioPciDevice {
|
|||||||
match cap {
|
match cap {
|
||||||
VfioRegionInfoCap::SparseMmap(sparse_mmap) => return Ok(sparse_mmap.areas.clone()),
|
VfioRegionInfoCap::SparseMmap(sparse_mmap) => return Ok(sparse_mmap.areas.clone()),
|
||||||
VfioRegionInfoCap::MsixMappable => {
|
VfioRegionInfoCap::MsixMappable => {
|
||||||
if !Self::is_4k_aligned(region_start) {
|
if !is_4k_aligned(region_start) {
|
||||||
error!(
|
error!(
|
||||||
"Region start address 0x{:x} must be at least aligned on 4KiB",
|
"Region start address 0x{:x} must be at least aligned on 4KiB",
|
||||||
region_start
|
region_start
|
||||||
);
|
);
|
||||||
return Err(VfioPciError::RegionAlignment);
|
return Err(VfioPciError::RegionAlignment);
|
||||||
}
|
}
|
||||||
if !Self::is_4k_multiple(region_size) {
|
if !is_4k_multiple(region_size) {
|
||||||
error!(
|
error!(
|
||||||
"Region size 0x{:x} must be at least a multiple of 4KiB",
|
"Region size 0x{:x} must be at least a multiple of 4KiB",
|
||||||
region_size
|
region_size
|
||||||
@@ -1358,7 +1410,8 @@ impl VfioPciDevice {
|
|||||||
// the MSI-X PBA table, we must calculate the subregions
|
// the MSI-X PBA table, we must calculate the subregions
|
||||||
// around them, leading to a list of sparse areas.
|
// around them, leading to a list of sparse areas.
|
||||||
// We want to make sure we will still trap MMIO accesses
|
// We want to make sure we will still trap MMIO accesses
|
||||||
// to these MSI-X specific ranges.
|
// to these MSI-X specific ranges. If these region don't align
|
||||||
|
// with pagesize, we can achive it by enlarging its range.
|
||||||
//
|
//
|
||||||
// Using a BtreeMap as the list provided through the iterator is sorted
|
// Using a BtreeMap as the list provided through the iterator is sorted
|
||||||
// by key. This ensures proper split of the whole region.
|
// by key. This ensures proper split of the whole region.
|
||||||
@@ -1366,10 +1419,14 @@ impl VfioPciDevice {
|
|||||||
if let Some(msix) = vfio_msix {
|
if let Some(msix) = vfio_msix {
|
||||||
if region_index == msix.cap.table_bir() {
|
if region_index == msix.cap.table_bir() {
|
||||||
let (offset, size) = msix.cap.table_range();
|
let (offset, size) = msix.cap.table_range();
|
||||||
|
let offset = align_page_size_down(offset);
|
||||||
|
let size = align_page_size_up(size);
|
||||||
inter_ranges.insert(offset, size);
|
inter_ranges.insert(offset, size);
|
||||||
}
|
}
|
||||||
if region_index == msix.cap.pba_bir() {
|
if region_index == msix.cap.pba_bir() {
|
||||||
let (offset, size) = msix.cap.pba_range();
|
let (offset, size) = msix.cap.pba_range();
|
||||||
|
let offset = align_page_size_down(offset);
|
||||||
|
let size = align_page_size_up(size);
|
||||||
inter_ranges.insert(offset, size);
|
inter_ranges.insert(offset, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1383,8 +1440,7 @@ impl VfioPciDevice {
|
|||||||
size: range_offset - current_offset,
|
size: range_offset - current_offset,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
current_offset = align_page_size_down(range_offset + range_size);
|
||||||
current_offset = Self::align_4k(range_offset + range_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if region_size > current_offset {
|
if region_size > current_offset {
|
||||||
@@ -1482,6 +1538,15 @@ impl VfioPciDevice {
|
|||||||
return Err(VfioPciError::MmapArea);
|
return Err(VfioPciError::MmapArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !is_page_size_aligned(area.size) || !is_page_size_aligned(area.offset) {
|
||||||
|
warn!(
|
||||||
|
"Could not mmap sparse area that is not page size aligned (offset = 0x{:x}, size = 0x{:x})",
|
||||||
|
area.offset,
|
||||||
|
area.size,
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let user_memory_region = UserMemoryRegion {
|
let user_memory_region = UserMemoryRegion {
|
||||||
slot: (self.memory_slot)(),
|
slot: (self.memory_slot)(),
|
||||||
start: region.start.0 + area.offset,
|
start: region.start.0 + area.offset,
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ build = "../build.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
argh = "0.1.9"
|
argh = "0.1.9"
|
||||||
dirs = "4.0.0"
|
dirs = "5.0.0"
|
||||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
serde = { version = "1.0.164", features = ["rc", "derive"] }
|
||||||
serde_json = "1.0.93"
|
serde_json = "1.0.96"
|
||||||
test_infra = { path = "../test_infra" }
|
test_infra = { path = "../test_infra" }
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.40"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|||||||
@@ -110,18 +110,23 @@ impl Default for MetricsReport {
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct PerformanceTestOverrides {
|
pub struct PerformanceTestOverrides {
|
||||||
test_iterations: Option<u32>,
|
test_iterations: Option<u32>,
|
||||||
|
test_timeout: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PerformanceTestOverrides {
|
impl fmt::Display for PerformanceTestOverrides {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if let Some(test_iterations) = self.test_iterations {
|
if let Some(test_iterations) = self.test_iterations {
|
||||||
write!(f, "test_iterations = {test_iterations}")?;
|
write!(f, "test_iterations = {test_iterations}, ")?;
|
||||||
|
}
|
||||||
|
if let Some(test_timeout) = self.test_timeout {
|
||||||
|
write!(f, "test_timeout = {test_timeout}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PerformanceTestControl {
|
pub struct PerformanceTestControl {
|
||||||
test_timeout: u32,
|
test_timeout: u32,
|
||||||
test_iterations: u32,
|
test_iterations: u32,
|
||||||
@@ -188,7 +193,14 @@ impl PerformanceTest {
|
|||||||
.test_iterations
|
.test_iterations
|
||||||
.unwrap_or(self.control.test_iterations)
|
.unwrap_or(self.control.test_iterations)
|
||||||
{
|
{
|
||||||
metrics.push((self.func_ptr)(&self.control));
|
// update the timeout in control if passed explicitly and run testcase with it
|
||||||
|
if let Some(test_timeout) = overrides.test_timeout {
|
||||||
|
let mut control: PerformanceTestControl = self.control.clone();
|
||||||
|
control.test_timeout = test_timeout;
|
||||||
|
metrics.push((self.func_ptr)(&control));
|
||||||
|
} else {
|
||||||
|
metrics.push((self.func_ptr)(&self.control));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mean = (self.unit_adjuster)(mean(&metrics).unwrap());
|
let mean = (self.unit_adjuster)(mean(&metrics).unwrap());
|
||||||
@@ -207,9 +219,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, test_iterations: &Option<u32>) -> u64 {
|
pub fn calc_timeout(&self, test_iterations: &Option<u32>, test_timeout: &Option<u32>) -> u64 {
|
||||||
((self.control.test_timeout + 20) * test_iterations.unwrap_or(self.control.test_iterations))
|
((test_timeout.unwrap_or(self.control.test_timeout) + 20)
|
||||||
as u64
|
* test_iterations.unwrap_or(self.control.test_iterations)) as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,6 +599,7 @@ fn run_test_with_timeout(
|
|||||||
) -> Result<PerformanceTestResult, Error> {
|
) -> Result<PerformanceTestResult, Error> {
|
||||||
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
|
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
|
||||||
let test_iterations = overrides.test_iterations;
|
let test_iterations = overrides.test_iterations;
|
||||||
|
let test_timeout = overrides.test_timeout;
|
||||||
let overrides = overrides.clone();
|
let overrides = overrides.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
println!(
|
println!(
|
||||||
@@ -609,7 +622,7 @@ fn run_test_with_timeout(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Todo: Need to cleanup/kill all hanging child processes
|
// Todo: Need to cleanup/kill all hanging child processes
|
||||||
let test_timeout = test.calc_timeout(&test_iterations);
|
let test_timeout = test.calc_timeout(&test_iterations, &test_timeout);
|
||||||
receiver
|
receiver
|
||||||
.recv_timeout(Duration::from_secs(test_timeout))
|
.recv_timeout(Duration::from_secs(test_timeout))
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
@@ -645,6 +658,10 @@ struct Options {
|
|||||||
/// override number of test iterations
|
/// override number of test iterations
|
||||||
iterations: Option<u32>,
|
iterations: Option<u32>,
|
||||||
|
|
||||||
|
#[argh(option, long = "timeout")]
|
||||||
|
/// override test timeout, Ex. --timeout 5
|
||||||
|
timeout: Option<u32>,
|
||||||
|
|
||||||
#[argh(switch, short = 'V', long = "version")]
|
#[argh(switch, short = 'V', long = "version")]
|
||||||
/// print version information
|
/// print version information
|
||||||
version: bool,
|
version: bool,
|
||||||
@@ -654,7 +671,7 @@ fn main() {
|
|||||||
let opts: Options = argh::from_env();
|
let opts: Options = argh::from_env();
|
||||||
|
|
||||||
if opts.version {
|
if opts.version {
|
||||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,6 +700,7 @@ fn main() {
|
|||||||
|
|
||||||
let overrides = Arc::new(PerformanceTestOverrides {
|
let overrides = Arc::new(PerformanceTestOverrides {
|
||||||
test_iterations: opts.iterations,
|
test_iterations: opts.iterations,
|
||||||
|
test_timeout: opts.timeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
for test in test_list.iter() {
|
for test in test_list.iter() {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "qcow"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["The Chromium OS Authors"]
|
|
||||||
edition = "2021"
|
|
||||||
license = "BSD-3-Clause"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/qcow.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
byteorder = "1.4.3"
|
|
||||||
libc = "0.2.139"
|
|
||||||
log = "0.4.17"
|
|
||||||
remain = "0.2.6"
|
|
||||||
vmm-sys-util = "0.11.0"
|
|
||||||
349
release-notes.md
349
release-notes.md
@@ -1,10 +1,36 @@
|
|||||||
|
- [v34.0](#v340)
|
||||||
|
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
|
||||||
|
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
|
||||||
|
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
|
||||||
|
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [v33.0](#v330)
|
||||||
|
- [D-Bus based API](#d-bus-based-api)
|
||||||
|
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||||
|
- [Contributors](#contributors-1)
|
||||||
|
- [v32.0](#v320)
|
||||||
|
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
||||||
|
- [API Changes](#api-changes)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||||
|
- [Contributors](#contributors-2)
|
||||||
|
- [v31.1](#v311)
|
||||||
|
- [v31.0](#v310)
|
||||||
|
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
||||||
|
- [Update Reference Kernel to 6.2](#update-reference-kernel-to-62)
|
||||||
|
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
|
||||||
|
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
|
||||||
|
- [Documentation Improvements](#documentation-improvements)
|
||||||
|
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||||
|
- [Contributors](#contributors-3)
|
||||||
- [v30.0](#v300)
|
- [v30.0](#v300)
|
||||||
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
||||||
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
||||||
- [Heap Profiling Support](#heap-profiling-support)
|
- [Heap Profiling Support](#heap-profiling-support)
|
||||||
- [Documentation Improvements](#documentation-improvements)
|
- [Documentation Improvements](#documentation-improvements-1)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors-4)
|
||||||
- [v28.2](#v282)
|
- [v28.2](#v282)
|
||||||
- [v29.0](#v290)
|
- [v29.0](#v290)
|
||||||
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
||||||
@@ -14,10 +40,10 @@
|
|||||||
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
||||||
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
||||||
- [TCP Offload Control](#tcp-offload-control)
|
- [TCP Offload Control](#tcp-offload-control)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||||
- [Removals](#removals)
|
- [Removals](#removals)
|
||||||
- [Deprecations](#deprecations)
|
- [Deprecations](#deprecations)
|
||||||
- [Contributors](#contributors-1)
|
- [Contributors](#contributors-5)
|
||||||
- [v28.1](#v281)
|
- [v28.1](#v281)
|
||||||
- [v28.0](#v280)
|
- [v28.0](#v280)
|
||||||
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
||||||
@@ -25,9 +51,9 @@
|
|||||||
- [Virtualised TPM Support](#virtualised-tpm-support)
|
- [Virtualised TPM Support](#virtualised-tpm-support)
|
||||||
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
||||||
- [README Quick Start Improved](#readme-quick-start-improved)
|
- [README Quick Start Improved](#readme-quick-start-improved)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||||
- [Removals](#removals-1)
|
- [Removals](#removals-1)
|
||||||
- [Contributors](#contributors-2)
|
- [Contributors](#contributors-6)
|
||||||
- [v27.0](#v270)
|
- [v27.0](#v270)
|
||||||
- [Community Engagement](#community-engagement)
|
- [Community Engagement](#community-engagement)
|
||||||
- [Prebuilt Packages](#prebuilt-packages)
|
- [Prebuilt Packages](#prebuilt-packages)
|
||||||
@@ -36,41 +62,41 @@
|
|||||||
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
||||||
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
||||||
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||||
- [Deprecations](#deprecations-1)
|
- [Deprecations](#deprecations-1)
|
||||||
- [Contributors](#contributors-3)
|
- [Contributors](#contributors-7)
|
||||||
- [v26.0](#v260)
|
- [v26.0](#v260)
|
||||||
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via-platform)
|
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
|
||||||
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||||
- [Deprecations](#deprecations-2)
|
- [Deprecations](#deprecations-2)
|
||||||
- [Removals](#removals-2)
|
- [Removals](#removals-2)
|
||||||
- [Contributors](#contributors-4)
|
- [Contributors](#contributors-8)
|
||||||
- [v25.0](#v250)
|
- [v25.0](#v250)
|
||||||
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
||||||
- [VM "Coredump" Support](#vm-coredump-support)
|
- [VM "Coredump" Support](#vm-coredump-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||||
- [Removals](#removals-3)
|
- [Removals](#removals-3)
|
||||||
- [Contributors](#contributors-5)
|
- [Contributors](#contributors-9)
|
||||||
- [v24.0](#v240)
|
- [v24.0](#v240)
|
||||||
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
||||||
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
||||||
- [Sparse Mmap support](#sparse-mmap-support)
|
- [Sparse Mmap support](#sparse-mmap-support)
|
||||||
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||||
- [Notable Improvements](#notable-improvements)
|
- [Notable Improvements](#notable-improvements)
|
||||||
- [Deprecations](#deprecations-3)
|
- [Deprecations](#deprecations-3)
|
||||||
- [New on the Website](#new-on-the-website)
|
- [New on the Website](#new-on-the-website)
|
||||||
- [Contributors](#contributors-6)
|
- [Contributors](#contributors-10)
|
||||||
- [v23.1](#v231)
|
- [v23.1](#v231)
|
||||||
- [v23.0](#v230)
|
- [v23.0](#v230)
|
||||||
- [vDPA Support](#vdpa-support)
|
- [vDPA Support](#vdpa-support)
|
||||||
- [Updated OS Support list](#updated-os-support-list)
|
- [Updated OS Support list](#updated-os-support-list)
|
||||||
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
||||||
- [`AMX` Support](#amx-support)
|
- [`AMX` Support](#amx-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||||
- [Deprecations](#deprecations-4)
|
- [Deprecations](#deprecations-4)
|
||||||
- [Contributors](#contributors-7)
|
- [Contributors](#contributors-11)
|
||||||
- [v22.1](#v221)
|
- [v22.1](#v221)
|
||||||
- [v22.0](#v220)
|
- [v22.0](#v220)
|
||||||
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
||||||
@@ -81,13 +107,13 @@
|
|||||||
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
||||||
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
||||||
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||||
- [Contributors](#contributors-8)
|
- [Contributors](#contributors-12)
|
||||||
- [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-9)
|
- [Notable Bug fixes](#notable-bug-fixes-13)
|
||||||
- [Contributors](#contributors-9)
|
- [Contributors](#contributors-13)
|
||||||
- [v20.2](#v202)
|
- [v20.2](#v202)
|
||||||
- [v20.1](#v201)
|
- [v20.1](#v201)
|
||||||
- [v20.0](#v200)
|
- [v20.0](#v200)
|
||||||
@@ -96,8 +122,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-10)
|
- [Notable bug fixes](#notable-bug-fixes-14)
|
||||||
- [Contributors](#contributors-10)
|
- [Contributors](#contributors-14)
|
||||||
- [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)
|
||||||
@@ -105,8 +131,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-11)
|
- [Notable bug fixes](#notable-bug-fixes-15)
|
||||||
- [Contributors](#contributors-11)
|
- [Contributors](#contributors-15)
|
||||||
- [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)
|
||||||
@@ -116,31 +142,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-12)
|
- [Notable bug fixes](#notable-bug-fixes-16)
|
||||||
- [Contributors](#contributors-12)
|
- [Contributors](#contributors-16)
|
||||||
- [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-13)
|
- [Notable bug fixes](#notable-bug-fixes-17)
|
||||||
- [Contributors](#contributors-13)
|
- [Contributors](#contributors-17)
|
||||||
- [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-14)
|
- [Notable bug fixes](#notable-bug-fixes-18)
|
||||||
- [Removed functionality](#removed-functionality)
|
- [Removed functionality](#removed-functionality)
|
||||||
- [Contributors](#contributors-14)
|
- [Contributors](#contributors-18)
|
||||||
- [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-5)
|
- [Deprecations](#deprecations-5)
|
||||||
- [Contributors](#contributors-15)
|
- [Contributors](#contributors-19)
|
||||||
- [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)
|
||||||
@@ -150,7 +176,7 @@
|
|||||||
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
||||||
- [Block device rate limiting](#block-device-rate-limiting)
|
- [Block device rate limiting](#block-device-rate-limiting)
|
||||||
- [Deprecations](#deprecations-6)
|
- [Deprecations](#deprecations-6)
|
||||||
- [Contributors](#contributors-16)
|
- [Contributors](#contributors-20)
|
||||||
- [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)
|
||||||
@@ -158,13 +184,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-17)
|
- [Contributors](#contributors-21)
|
||||||
- [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-18)
|
- [Contributors](#contributors-22)
|
||||||
- [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)
|
||||||
@@ -174,17 +200,17 @@
|
|||||||
- [Improved Linux Boot Time](#improved-linux-boot-time)
|
- [Improved Linux Boot Time](#improved-linux-boot-time)
|
||||||
- [`SIGTERM/SIGINT` Interrupt Signal Handling](#sigtermsigint-interrupt-signal-handling)
|
- [`SIGTERM/SIGINT` Interrupt Signal Handling](#sigtermsigint-interrupt-signal-handling)
|
||||||
- [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-15)
|
- [Notable Bug Fixes](#notable-bug-fixes-19)
|
||||||
- [Contributors](#contributors-19)
|
- [Contributors](#contributors-23)
|
||||||
- [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-16)
|
- [Notable Bug Fixes](#notable-bug-fixes-20)
|
||||||
- [Contributors](#contributors-20)
|
- [Contributors](#contributors-24)
|
||||||
- [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)
|
||||||
@@ -197,17 +223,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-17)
|
- [Notable Bug Fixes](#notable-bug-fixes-21)
|
||||||
- [Contributors](#contributors-21)
|
- [Contributors](#contributors-25)
|
||||||
- [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-18)
|
- [Notable Bug Fixes](#notable-bug-fixes-22)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||||
- [Contributors](#contributors-22)
|
- [Contributors](#contributors-26)
|
||||||
- [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)
|
||||||
@@ -217,14 +243,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-23)
|
- [Contributors](#contributors-27)
|
||||||
- [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-24)
|
- [Contributors](#contributors-28)
|
||||||
- [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)
|
||||||
@@ -232,7 +258,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-25)
|
- [Contributors](#contributors-29)
|
||||||
- [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)
|
||||||
@@ -241,7 +267,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-26)
|
- [Contributors](#contributors-30)
|
||||||
- [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)
|
||||||
@@ -268,6 +294,229 @@
|
|||||||
- [Unit testing](#unit-testing)
|
- [Unit testing](#unit-testing)
|
||||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||||
|
|
||||||
|
# v34.0
|
||||||
|
|
||||||
|
This release has been tracked in our [roadmap
|
||||||
|
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||||
|
v34.0. The following user visible changes have been made:
|
||||||
|
|
||||||
|
### Paravirtualised Panic Device Support
|
||||||
|
|
||||||
|
A new device has been added that can communicate when the guest kernel has
|
||||||
|
panicked and share those details with the VMM. This is controlled with a new
|
||||||
|
`--pvpanic` command line option and JSON API change equivalent. (#5526)
|
||||||
|
|
||||||
|
### Improvements to VM Core Dump
|
||||||
|
|
||||||
|
Requesting to dump the guest memory as core dump will now transparently pause
|
||||||
|
the VM if required; returning to the original state after. (#5604)
|
||||||
|
|
||||||
|
### QCOW2 Support for Backing Files
|
||||||
|
|
||||||
|
The support for QCOW2 files has been enhanced to include support for using
|
||||||
|
backing files. (#5573)
|
||||||
|
|
||||||
|
### Minimum Host Kernel Bump
|
||||||
|
|
||||||
|
The minimum supported host kernel is now 5.13 in order to incorporate a bug fix
|
||||||
|
for `KVM_FEATURE_ASYNC_PF_INT` functionality. (#5626)
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* The x86 emulator is only compiled in if MSHV is compiled in (the kernel
|
||||||
|
carries out this job with KVM) (#5561).
|
||||||
|
* A regression has been fixed in VFIO support for devices that use MSI rather
|
||||||
|
than MSI-X (#5658).
|
||||||
|
* When triggering a VM shutdown or reset via I/O the vCPU thread will be
|
||||||
|
blocked until that asynchronous event has been received (#5645).
|
||||||
|
* Pausing a VM is now a synchronous action with the request only completing
|
||||||
|
when all vCPUs are paused (#5611).
|
||||||
|
* Event monitor support now correctly supports concurrent access (#5633).
|
||||||
|
* Bug fixes for the QCOW2 file support (#5573).
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Changyuan Lyu <changyuanl@google.com>
|
||||||
|
* Christian Blichmann <cblichmann@google.com>
|
||||||
|
* Manish Goregaokar <manishsmail@gmail.com>
|
||||||
|
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||||
|
* Philipp Schuster <philipp.schuster@cyberus-technology.de>
|
||||||
|
* Praveen K Paladugu <prapal@linux.microsoft.com>
|
||||||
|
* Rob Bradford <rbradford@rivosinc.com>
|
||||||
|
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||||
|
* Yi Wang <foxywang@tencent.com>
|
||||||
|
* Yong He <alexyonghe@tencent.com>
|
||||||
|
* Yu Li <liyu.yukiteru@bytedance.com>
|
||||||
|
* dom.song <dom.song@amperecomputing.com>
|
||||||
|
|
||||||
|
# v33.0
|
||||||
|
|
||||||
|
This release has been tracked in our [roadmap
|
||||||
|
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||||
|
v33.0. The following user visible changes have been made:
|
||||||
|
|
||||||
|
### D-Bus based API
|
||||||
|
|
||||||
|
A D-Bus based API has been added as an alternative to the existing REST
|
||||||
|
API. This feature is gated by the `dbus_api` feature. Details can be
|
||||||
|
found in the [API documentation](docs/api.md).
|
||||||
|
|
||||||
|
### Expose Host CPU Cache Details for AArch64
|
||||||
|
|
||||||
|
Now the CPU cache information on the host is properly exposed to the
|
||||||
|
guest on AArch64.
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Report errors explicitly to users when VM failed to boot (#5453)
|
||||||
|
* Fix VFIO on platforms with non-4k page size (#5450, #5469)
|
||||||
|
* Fix TDX initialization (#5454)
|
||||||
|
* Ensure all guest memory regions are page-size aligned (#5496)
|
||||||
|
* Fix seccomp filter lists related to virtio-console, serial and pty
|
||||||
|
(#5506, #5524)
|
||||||
|
* Populate APIC ID properly (#5512)
|
||||||
|
* Ignore and warn TAP FDs in more situations (#5522)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Jianyong Wu <jianyong.wu@arm.com>
|
||||||
|
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||||
|
* Rafael Mendonca <rafaelmendsr@gmail.com>
|
||||||
|
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||||
|
* Rob Bradford <rbradford@rivosinc.com>
|
||||||
|
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||||
|
* Yu Li <liyu.yukiteru@bytedance.com>
|
||||||
|
* zhongbingnan <zhongbingnan@bytedance.com>
|
||||||
|
|
||||||
|
# v32.0
|
||||||
|
|
||||||
|
This release has been tracked in our [roadmap
|
||||||
|
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||||
|
v32.0. The following user visible changes have been made:
|
||||||
|
|
||||||
|
### Increased PCI Segment Limit
|
||||||
|
|
||||||
|
The maximum number of PCI segments that can be used is now 96 (up from 16).
|
||||||
|
|
||||||
|
### API Changes
|
||||||
|
|
||||||
|
* The VmmPingResponse now includes the PID as well as the build details.
|
||||||
|
(#5348)
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Ignore and warn TAP FDs sent via the HTTP request body (#5350)
|
||||||
|
* Properly preserve and close valid FDs for TAP devices (#5373)
|
||||||
|
* Only use `KVM_ARM_VCPU_PMU_V3` if available (#5360)
|
||||||
|
* Only touch the tty flags if it's being used (#5343)
|
||||||
|
* Fix seccomp filter lists for vhost-user devices (#5361)
|
||||||
|
* The number of vCPUs is capped at the hypervisor maximum (#5357)
|
||||||
|
* Fixes for TTY reset (#5414)
|
||||||
|
* CPU topology fixes on MSHV (#5325)
|
||||||
|
* Seccomp fixes for older distributions (#5397)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Hao Xu <howeyxu@tencent.com>
|
||||||
|
* Muminul Islam <muislam@microsoft.com>
|
||||||
|
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||||
|
* Rafael Mendonca <rafaelmendsr@gmail.com>
|
||||||
|
* Rob Bradford <rbradford@rivosinc.com>
|
||||||
|
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||||
|
* Smit Gardhariya <gardhariya.smit@gmail.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
|
||||||
|
# v31.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Ignore and warn TAP FDs sent via the HTTP request body (#5350)
|
||||||
|
* Properly preserve and close valid FDs for TAP devices (#5373)
|
||||||
|
* Only use `KVM_ARM_VCPU_PMU_V3` if available (#5360)
|
||||||
|
* Only touch the tty flags if it's being used (#5343)
|
||||||
|
* Fix seccomp filter lists for vhost-user devices (#5361)
|
||||||
|
|
||||||
|
# v31.0
|
||||||
|
|
||||||
|
This release has been tracked in our [roadmap
|
||||||
|
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||||
|
v31.0. The following user visible changes have been made:
|
||||||
|
|
||||||
|
### Update to Latest `acpi_tables`
|
||||||
|
|
||||||
|
Adapted to the latest [acpi_tables](https://github.com/rust-vmm/acpi_tables).
|
||||||
|
There has been significant API changes in the crate.
|
||||||
|
|
||||||
|
### Update Reference Kernel to 6.2
|
||||||
|
|
||||||
|
Updated the recommended guest kernel version from 6.1.6 to 6.2.
|
||||||
|
|
||||||
|
### Improvements on Console `SIGWINCH` Handler
|
||||||
|
|
||||||
|
A separate thread had been created to capture the `SIGWINCH` signal and resize
|
||||||
|
the guest console. Now the thread is skipped if the console is not resizable.
|
||||||
|
|
||||||
|
Two completely different code paths existed for handling console resizing, one
|
||||||
|
for `tty` and the other for `pty`. That makes the understanding of the console
|
||||||
|
handling code unnecessarily complicated. Now the code paths are unified. Both
|
||||||
|
`tty` and `pty` are supported in single `SIGWINCH` handler. And the new handler
|
||||||
|
can works with kernel versions earlier than v5.5.
|
||||||
|
|
||||||
|
### Remove Directory Support from `MemoryZoneConfig::file`
|
||||||
|
|
||||||
|
Setting a directory to `MemoryZoneConfig::file` is no longer supported.
|
||||||
|
|
||||||
|
Before this change, user can set a directory to `file` of the `--memory-zone`
|
||||||
|
option. In that case, a temporary file will be created as the backing file for
|
||||||
|
the `mmap(2)` operation. This functionality has been unnecessary since we had
|
||||||
|
the native support for hugepages and allocating anonymous shared memory.
|
||||||
|
|
||||||
|
### Documentation Improvements
|
||||||
|
|
||||||
|
* Various improvements in API document
|
||||||
|
* Improvements in Doc comments
|
||||||
|
* Updated Slack channel information in README
|
||||||
|
|
||||||
|
### Notable Bug Fixes
|
||||||
|
|
||||||
|
* Fixed the offset setting while removing the entire mapping of `vhost-user` FS
|
||||||
|
client.
|
||||||
|
* Fixed the `ShutdownVmm` and `Shutdown` commands to call the correct API
|
||||||
|
endpoint.
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Daniel Farina <daniel@fdr.io>
|
||||||
|
* Dom <peng6662001@163.com>
|
||||||
|
* Hao Xu <howeyxu@tencent.com>
|
||||||
|
* Muminul Islam <muislam@microsoft.com>
|
||||||
|
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||||
|
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||||
|
* Rob Bradford <rbradford@rivosinc.com>
|
||||||
|
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||||
|
* Smit Gardhariya <gardhariya.smit@gmail.com>
|
||||||
|
* Yang <ailin.yang@intel.com>
|
||||||
|
* Yong He <alexyonghe@tencent.com>
|
||||||
|
|
||||||
# v30.0
|
# v30.0
|
||||||
|
|
||||||
This release has been tracked in our [roadmap
|
This release has been tracked in our [roadmap
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
# When changing this file don't forget to update the tag name in the
|
# When changing this file don't forget to update the tag name in the
|
||||||
# .github/workflows/docker-image.yaml file if doing multiple per day
|
# .github/workflows/docker-image.yaml file if doing multiple per day
|
||||||
|
|
||||||
FROM ubuntu:20.04 as dev
|
FROM ubuntu:20.04 as dev
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG RUST_TOOLCHAIN="1.66.1"
|
ARG RUST_TOOLCHAIN="1.67.1"
|
||||||
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"
|
||||||
@@ -13,58 +15,67 @@ ARG CARGO_GIT_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_git_registry"
|
|||||||
ENV CARGO_HOME=/usr/local/rust
|
ENV CARGO_HOME=/usr/local/rust
|
||||||
ENV RUSTUP_HOME=$CARGO_HOME
|
ENV RUSTUP_HOME=$CARGO_HOME
|
||||||
ENV PATH="$PATH:$CARGO_HOME/bin"
|
ENV PATH="$PATH:$CARGO_HOME/bin"
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# Install all CI dependencies
|
# Install all CI dependencies
|
||||||
|
# DL3015 ignored cause not installing openvswitch-switch-dpdk recommended packages breaks ovs_dpdk test
|
||||||
|
# hadolint ignore=DL3008,DL3015
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -yq upgrade \
|
&& apt-get -yq upgrade \
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq \
|
&& apt-get install --no-install-recommends -yq \
|
||||||
build-essential \
|
build-essential \
|
||||||
bc \
|
bc \
|
||||||
curl \
|
curl \
|
||||||
wget \
|
wget \
|
||||||
sudo \
|
sudo \
|
||||||
mtools \
|
mtools \
|
||||||
musl-tools \
|
musl-tools \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
flex \
|
flex \
|
||||||
bison \
|
bison \
|
||||||
libelf-dev \
|
libelf-dev \
|
||||||
qemu-utils \
|
qemu-utils \
|
||||||
libglib2.0-dev \
|
libglib2.0-dev \
|
||||||
libpixman-1-dev \
|
libpixman-1-dev \
|
||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
libcap-ng-dev \
|
libcap-ng-dev \
|
||||||
socat \
|
socat \
|
||||||
dosfstools \
|
dosfstools \
|
||||||
cpio \
|
cpio \
|
||||||
python \
|
python \
|
||||||
python3 \
|
python3 \
|
||||||
python3-setuptools \
|
python3-setuptools \
|
||||||
ntfs-3g \
|
ntfs-3g \
|
||||||
openvswitch-switch-dpdk \
|
python3-distutils \
|
||||||
python3-distutils \
|
uuid-dev \
|
||||||
uuid-dev \
|
iperf3 \
|
||||||
iperf3 \
|
zip \
|
||||||
zip \
|
git-core \
|
||||||
git-core \
|
dnsmasq \
|
||||||
dnsmasq \
|
dmsetup \
|
||||||
dmsetup \
|
ca-certificates \
|
||||||
|
unzip \
|
||||||
|
iproute2 \
|
||||||
|
dbus \
|
||||||
|
&& apt-get install openvswitch-switch-dpdk -yq \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/* /var/log/*log /var/log/apt/* /var/lib/dpkg/*-old /var/cache/debconf/*-old
|
||||||
|
|
||||||
RUN update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
|
RUN update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
|
||||||
|
|
||||||
|
# hadolint ignore=DL3008
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
apt-get update \
|
apt-get update \
|
||||||
&& apt-get -yq upgrade \
|
&& apt-get -yq upgrade \
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc-multilib gawk \
|
&& apt-get install --no-install-recommends -yq gcc-multilib gawk \
|
||||||
libtool expect gnutls-dev gnutls-bin libfuse-dev \
|
libtool expect gnutls-dev gnutls-bin libfuse-dev \
|
||||||
libjson-glib-dev libgmp-dev libtasn1-dev python3-twisted \
|
libjson-glib-dev libgmp-dev libtasn1-dev python3-twisted \
|
||||||
net-tools softhsm2 \
|
net-tools softhsm2 \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*; fi
|
&& rm -rf /var/lib/apt/lists/* /var/log/*log /var/log/apt/* /var/lib/dpkg/*-old /var/cache/debconf/*-old; fi
|
||||||
|
|
||||||
|
# hadolint ignore=DL3008
|
||||||
RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
||||||
# On AArch64, `setcap` binary should be installed via `libcap2-bin`.
|
# On AArch64, `setcap` binary should be installed via `libcap2-bin`.
|
||||||
# The `setcap` binary is used in integration tests.
|
# The `setcap` binary is used in integration tests.
|
||||||
@@ -72,7 +83,7 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
|||||||
# kernel (any version) image in `/boot` and modules in `/lib/modules`.
|
# kernel (any version) image in `/boot` and modules in `/lib/modules`.
|
||||||
apt-get update \
|
apt-get update \
|
||||||
&& apt-get -yq upgrade \
|
&& apt-get -yq upgrade \
|
||||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq \
|
&& apt-get install --no-install-recommends -yq \
|
||||||
libcap2-bin \
|
libcap2-bin \
|
||||||
libguestfs-tools \
|
libguestfs-tools \
|
||||||
linux-image-generic \
|
linux-image-generic \
|
||||||
@@ -82,11 +93,12 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
|||||||
perl \
|
perl \
|
||||||
texinfo \
|
texinfo \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*; fi
|
&& rm -rf /var/lib/apt/lists/* /var/log/*log /var/log/apt/* /var/lib/dpkg/*-old /var/cache/debconf/*-old; fi
|
||||||
|
|
||||||
# Fix the libssl-dev install
|
# Fix the libssl-dev install
|
||||||
|
# hadolint ignore=SC2155
|
||||||
RUN export ARCH="$(uname -m)" \
|
RUN export ARCH="$(uname -m)" \
|
||||||
&& cp /usr/include/$ARCH-linux-gnu/openssl/opensslconf.h /usr/include/openssl/
|
&& cp /usr/include/"$ARCH"-linux-gnu/openssl/opensslconf.h /usr/include/openssl/
|
||||||
ENV X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu/
|
ENV X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu/
|
||||||
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu/
|
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu/
|
||||||
ENV AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu/
|
ENV AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu/
|
||||||
@@ -94,9 +106,10 @@ ENV AARCH64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu/
|
|||||||
ENV OPENSSL_INCLUDE_DIR=/usr/include/
|
ENV OPENSSL_INCLUDE_DIR=/usr/include/
|
||||||
|
|
||||||
# Install the rust toolchain
|
# Install the rust toolchain
|
||||||
|
# hadolint ignore=DL4006,SC2155
|
||||||
RUN export ARCH="$(uname -m)" \
|
RUN export ARCH="$(uname -m)" \
|
||||||
&& nohup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "$RUST_TOOLCHAIN" \
|
&& nohup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "$RUST_TOOLCHAIN" \
|
||||||
&& rustup target add $ARCH-unknown-linux-musl --toolchain "$RUST_TOOLCHAIN" \
|
&& rustup target add "$ARCH"-unknown-linux-musl --toolchain "$RUST_TOOLCHAIN" \
|
||||||
&& if [ "$TARGETARCH" = "amd64" ]; then rustup toolchain add --profile minimal $RUST_TOOLCHAIN-x86_64-unknown-linux-musl; fi \
|
&& if [ "$TARGETARCH" = "amd64" ]; then rustup toolchain add --profile minimal $RUST_TOOLCHAIN-x86_64-unknown-linux-musl; fi \
|
||||||
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add rustfmt; fi \
|
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add rustfmt; fi \
|
||||||
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add clippy; fi \
|
&& if [ "$TARGETARCH" = "amd64" ]; then rustup component add clippy; fi \
|
||||||
@@ -106,12 +119,14 @@ RUN export ARCH="$(uname -m)" \
|
|||||||
&& ln -s "$CARGO_GIT_REGISTRY_DIR" "$CARGO_HOME/git"
|
&& ln -s "$CARGO_GIT_REGISTRY_DIR" "$CARGO_HOME/git"
|
||||||
|
|
||||||
# Set the rust environment
|
# Set the rust environment
|
||||||
RUN echo 'source $CARGO_HOME/env' >> $HOME/.bashrc \
|
# hadolint ignore=SC2016
|
||||||
&& mkdir $HOME/.cargo \
|
RUN echo 'source $CARGO_HOME/env' >> "$HOME"/.bashrc \
|
||||||
&& ln -s $CARGO_HOME/env $HOME/.cargo/env
|
&& mkdir "$HOME"/.cargo \
|
||||||
|
&& ln -s $CARGO_HOME/env "$HOME"/.cargo/env
|
||||||
|
|
||||||
# install SPDK NVMe
|
# install SPDK NVMe
|
||||||
# only for 'x86_64' platform images as 'docker buildx' can't build 'spdk'
|
# only for 'x86_64' platform images as 'docker buildx' can't build 'spdk'
|
||||||
|
# hadolint ignore=DL3003,SC2046
|
||||||
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 \
|
||||||
@@ -121,7 +136,7 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
|||||||
&& ./scripts/pkgdep.sh \
|
&& ./scripts/pkgdep.sh \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& ./configure --with-vfio-user \
|
&& ./configure --with-vfio-user \
|
||||||
&& make -j `nproc` \
|
&& make -j $(nproc) TARGET_ARCHITECTURE=skylake \
|
||||||
&& mkdir /usr/local/bin/spdk-nvme \
|
&& mkdir /usr/local/bin/spdk-nvme \
|
||||||
&& cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
&& cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
||||||
&& cp ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
&& cp ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
||||||
@@ -129,6 +144,7 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
|||||||
&& cd .. && rm -rf spdk; fi
|
&& cd .. && rm -rf spdk; fi
|
||||||
|
|
||||||
# install swtpm only for x86_64 arch
|
# install swtpm only for x86_64 arch
|
||||||
|
# hadolint ignore=DL3003
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
git clone https://github.com/stefanberger/libtpms libtpms_build \
|
git clone https://github.com/stefanberger/libtpms libtpms_build \
|
||||||
&& cd libtpms_build \
|
&& cd libtpms_build \
|
||||||
@@ -149,7 +165,7 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
|||||||
|
|
||||||
# install ethr tool for performance tests
|
# install ethr tool for performance tests
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
wget https://github.com/microsoft/ethr/releases/latest/download/ethr_linux.zip \
|
wget -nv https://github.com/microsoft/ethr/releases/latest/download/ethr_linux.zip \
|
||||||
&& unzip ethr_linux.zip \
|
&& unzip ethr_linux.zip \
|
||||||
&& cp ethr /usr/local/bin \
|
&& cp ethr /usr/local/bin \
|
||||||
&& rm ethr_linux.zip; fi
|
&& rm ethr_linux.zip; fi
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Linux/arm64 6.1.6 Kernel Configuration
|
# Linux/arm64 6.2.0 Kernel Configuration
|
||||||
#
|
#
|
||||||
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
|
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
|
||||||
CONFIG_CC_IS_GCC=y
|
CONFIG_CC_IS_GCC=y
|
||||||
@@ -55,7 +55,6 @@ CONFIG_IRQ_DOMAIN=y
|
|||||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||||
CONFIG_GENERIC_IRQ_IPI=y
|
CONFIG_GENERIC_IRQ_IPI=y
|
||||||
CONFIG_GENERIC_MSI_IRQ=y
|
CONFIG_GENERIC_MSI_IRQ=y
|
||||||
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
|
|
||||||
CONFIG_IRQ_MSI_IOMMU=y
|
CONFIG_IRQ_MSI_IOMMU=y
|
||||||
CONFIG_IRQ_FORCED_THREADING=y
|
CONFIG_IRQ_FORCED_THREADING=y
|
||||||
CONFIG_SPARSE_IRQ=y
|
CONFIG_SPARSE_IRQ=y
|
||||||
@@ -203,6 +202,7 @@ CONFIG_INITRAMFS_PRESERVE_MTIME=y
|
|||||||
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
||||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||||
CONFIG_LD_ORPHAN_WARN=y
|
CONFIG_LD_ORPHAN_WARN=y
|
||||||
|
CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
|
||||||
CONFIG_SYSCTL=y
|
CONFIG_SYSCTL=y
|
||||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||||
CONFIG_EXPERT=y
|
CONFIG_EXPERT=y
|
||||||
@@ -227,6 +227,7 @@ CONFIG_IO_URING=y
|
|||||||
CONFIG_ADVISE_SYSCALLS=y
|
CONFIG_ADVISE_SYSCALLS=y
|
||||||
CONFIG_MEMBARRIER=y
|
CONFIG_MEMBARRIER=y
|
||||||
CONFIG_KALLSYMS=y
|
CONFIG_KALLSYMS=y
|
||||||
|
# CONFIG_KALLSYMS_SELFTEST is not set
|
||||||
# CONFIG_KALLSYMS_ALL is not set
|
# CONFIG_KALLSYMS_ALL is not set
|
||||||
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
||||||
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
|
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
|
||||||
@@ -249,7 +250,7 @@ CONFIG_PERF_EVENTS=y
|
|||||||
# end of General setup
|
# end of General setup
|
||||||
|
|
||||||
CONFIG_ARM64=y
|
CONFIG_ARM64=y
|
||||||
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y
|
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||||
CONFIG_64BIT=y
|
CONFIG_64BIT=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
CONFIG_ARM64_PAGE_SHIFT=12
|
CONFIG_ARM64_PAGE_SHIFT=12
|
||||||
@@ -349,6 +350,7 @@ CONFIG_ARM64_ERRATUM_2054223=y
|
|||||||
CONFIG_ARM64_ERRATUM_2067961=y
|
CONFIG_ARM64_ERRATUM_2067961=y
|
||||||
CONFIG_ARM64_ERRATUM_2441009=y
|
CONFIG_ARM64_ERRATUM_2441009=y
|
||||||
CONFIG_ARM64_ERRATUM_2457168=y
|
CONFIG_ARM64_ERRATUM_2457168=y
|
||||||
|
CONFIG_ARM64_ERRATUM_2645198=y
|
||||||
CONFIG_CAVIUM_ERRATUM_22375=y
|
CONFIG_CAVIUM_ERRATUM_22375=y
|
||||||
CONFIG_CAVIUM_ERRATUM_23144=y
|
CONFIG_CAVIUM_ERRATUM_23144=y
|
||||||
CONFIG_CAVIUM_ERRATUM_23154=y
|
CONFIG_CAVIUM_ERRATUM_23154=y
|
||||||
@@ -376,7 +378,7 @@ CONFIG_ARM64_PA_BITS=48
|
|||||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
# CONFIG_CPU_BIG_ENDIAN is not set
|
||||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||||
CONFIG_SCHED_MC=y
|
CONFIG_SCHED_MC=y
|
||||||
CONFIG_SCHED_CLUSTER is not set
|
# CONFIG_SCHED_CLUSTER is not set
|
||||||
CONFIG_SCHED_SMT=y
|
CONFIG_SCHED_SMT=y
|
||||||
CONFIG_NR_CPUS=128
|
CONFIG_NR_CPUS=128
|
||||||
CONFIG_HOTPLUG_CPU=y
|
CONFIG_HOTPLUG_CPU=y
|
||||||
@@ -471,7 +473,6 @@ CONFIG_RANDOMIZE_BASE=y
|
|||||||
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
|
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
|
||||||
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
||||||
CONFIG_STACKPROTECTOR_PER_TASK=y
|
CONFIG_STACKPROTECTOR_PER_TASK=y
|
||||||
CONFIG_ARCH_NR_GPIO=0
|
|
||||||
# end of Kernel Features
|
# end of Kernel Features
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -559,6 +560,7 @@ CONFIG_ACPI_GENERIC_GSI=y
|
|||||||
CONFIG_ACPI_CCA_REQUIRED=y
|
CONFIG_ACPI_CCA_REQUIRED=y
|
||||||
# CONFIG_ACPI_DEBUGGER is not set
|
# CONFIG_ACPI_DEBUGGER is not set
|
||||||
CONFIG_ACPI_SPCR_TABLE=y
|
CONFIG_ACPI_SPCR_TABLE=y
|
||||||
|
# CONFIG_ACPI_FPDT is not set
|
||||||
# CONFIG_ACPI_EC_DEBUGFS is not set
|
# CONFIG_ACPI_EC_DEBUGFS is not set
|
||||||
# CONFIG_ACPI_AC is not set
|
# CONFIG_ACPI_AC is not set
|
||||||
# CONFIG_ACPI_BATTERY is not set
|
# CONFIG_ACPI_BATTERY is not set
|
||||||
@@ -591,8 +593,10 @@ CONFIG_HAVE_ACPI_APEI=y
|
|||||||
# CONFIG_ACPI_PFRUT is not set
|
# CONFIG_ACPI_PFRUT is not set
|
||||||
CONFIG_ACPI_IORT=y
|
CONFIG_ACPI_IORT=y
|
||||||
CONFIG_ACPI_GTDT=y
|
CONFIG_ACPI_GTDT=y
|
||||||
|
CONFIG_ACPI_APMT=y
|
||||||
CONFIG_ACPI_PPTT=y
|
CONFIG_ACPI_PPTT=y
|
||||||
# CONFIG_ACPI_PCC is not set
|
# CONFIG_ACPI_PCC is not set
|
||||||
|
# CONFIG_ACPI_FFH is not set
|
||||||
# CONFIG_PMIC_OPREGION is not set
|
# CONFIG_PMIC_OPREGION is not set
|
||||||
CONFIG_ACPI_VIOT=y
|
CONFIG_ACPI_VIOT=y
|
||||||
# CONFIG_ACPI_PRMT is not set
|
# CONFIG_ACPI_PRMT is not set
|
||||||
@@ -601,6 +605,9 @@ CONFIG_HAVE_KVM=y
|
|||||||
CONFIG_HAVE_KVM_IRQCHIP=y
|
CONFIG_HAVE_KVM_IRQCHIP=y
|
||||||
CONFIG_HAVE_KVM_IRQFD=y
|
CONFIG_HAVE_KVM_IRQFD=y
|
||||||
CONFIG_HAVE_KVM_IRQ_ROUTING=y
|
CONFIG_HAVE_KVM_IRQ_ROUTING=y
|
||||||
|
CONFIG_HAVE_KVM_DIRTY_RING=y
|
||||||
|
CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y
|
||||||
|
CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y
|
||||||
CONFIG_HAVE_KVM_EVENTFD=y
|
CONFIG_HAVE_KVM_EVENTFD=y
|
||||||
CONFIG_KVM_MMIO=y
|
CONFIG_KVM_MMIO=y
|
||||||
CONFIG_HAVE_KVM_MSI=y
|
CONFIG_HAVE_KVM_MSI=y
|
||||||
@@ -654,6 +661,7 @@ CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
|
|||||||
CONFIG_MMU_GATHER_TABLE_FREE=y
|
CONFIG_MMU_GATHER_TABLE_FREE=y
|
||||||
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
||||||
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
||||||
|
CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y
|
||||||
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
||||||
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
||||||
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
||||||
@@ -718,6 +726,7 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
|
|||||||
# end of GCOV-based kernel profiling
|
# end of GCOV-based kernel profiling
|
||||||
|
|
||||||
CONFIG_HAVE_GCC_PLUGINS=y
|
CONFIG_HAVE_GCC_PLUGINS=y
|
||||||
|
CONFIG_FUNCTION_ALIGNMENT=0
|
||||||
# end of General architecture-dependent options
|
# end of General architecture-dependent options
|
||||||
|
|
||||||
CONFIG_RT_MUTEXES=y
|
CONFIG_RT_MUTEXES=y
|
||||||
@@ -884,7 +893,8 @@ CONFIG_ZSMALLOC_STAT=y
|
|||||||
#
|
#
|
||||||
# CONFIG_SLAB is not set
|
# CONFIG_SLAB is not set
|
||||||
CONFIG_SLUB=y
|
CONFIG_SLUB=y
|
||||||
# CONFIG_SLOB is not set
|
# CONFIG_SLOB_DEPRECATED is not set
|
||||||
|
# CONFIG_SLUB_TINY is not set
|
||||||
CONFIG_SLAB_MERGE_DEFAULT=y
|
CONFIG_SLAB_MERGE_DEFAULT=y
|
||||||
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
||||||
CONFIG_SLAB_FREELIST_HARDENED=y
|
CONFIG_SLAB_FREELIST_HARDENED=y
|
||||||
@@ -951,6 +961,7 @@ CONFIG_ZONE_DMA32=y
|
|||||||
CONFIG_ZONE_DEVICE=y
|
CONFIG_ZONE_DEVICE=y
|
||||||
# CONFIG_DEVICE_PRIVATE is not set
|
# CONFIG_DEVICE_PRIVATE is not set
|
||||||
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
|
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
|
||||||
|
CONFIG_ARCH_USES_PG_ARCH_X=y
|
||||||
CONFIG_VM_EVENT_COUNTERS=y
|
CONFIG_VM_EVENT_COUNTERS=y
|
||||||
CONFIG_PERCPU_STATS=y
|
CONFIG_PERCPU_STATS=y
|
||||||
# CONFIG_GUP_TEST is not set
|
# CONFIG_GUP_TEST is not set
|
||||||
@@ -1122,7 +1133,6 @@ CONFIG_PCIE_PME=y
|
|||||||
# CONFIG_PCIE_DPC is not set
|
# CONFIG_PCIE_DPC is not set
|
||||||
# CONFIG_PCIE_PTM is not set
|
# CONFIG_PCIE_PTM is not set
|
||||||
CONFIG_PCI_MSI=y
|
CONFIG_PCI_MSI=y
|
||||||
CONFIG_PCI_MSI_IRQ_DOMAIN=y
|
|
||||||
CONFIG_PCI_QUIRKS=y
|
CONFIG_PCI_QUIRKS=y
|
||||||
CONFIG_PCI_DEBUG=y
|
CONFIG_PCI_DEBUG=y
|
||||||
CONFIG_PCI_STUB=y
|
CONFIG_PCI_STUB=y
|
||||||
@@ -1272,7 +1282,6 @@ CONFIG_EFI_RUNTIME_WRAPPERS=y
|
|||||||
CONFIG_EFI_GENERIC_STUB=y
|
CONFIG_EFI_GENERIC_STUB=y
|
||||||
# CONFIG_EFI_ZBOOT is not set
|
# CONFIG_EFI_ZBOOT is not set
|
||||||
CONFIG_EFI_ARMSTUB_DTB_LOADER=y
|
CONFIG_EFI_ARMSTUB_DTB_LOADER=y
|
||||||
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
|
||||||
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
||||||
# CONFIG_EFI_CAPSULE_LOADER is not set
|
# CONFIG_EFI_CAPSULE_LOADER is not set
|
||||||
# CONFIG_EFI_TEST is not set
|
# CONFIG_EFI_TEST is not set
|
||||||
@@ -1326,6 +1335,7 @@ CONFIG_ZRAM_DEF_COMP_LZORLE=y
|
|||||||
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
||||||
# CONFIG_ZRAM_WRITEBACK is not set
|
# CONFIG_ZRAM_WRITEBACK is not set
|
||||||
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
||||||
|
# CONFIG_ZRAM_MULTI_COMP is not set
|
||||||
CONFIG_BLK_DEV_LOOP=y
|
CONFIG_BLK_DEV_LOOP=y
|
||||||
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
||||||
# CONFIG_BLK_DEV_DRBD is not set
|
# CONFIG_BLK_DEV_DRBD is not set
|
||||||
@@ -1392,7 +1402,8 @@ CONFIG_NVME_MULTIPATH=y
|
|||||||
# CONFIG_MISC_RTSX_PCI is not set
|
# CONFIG_MISC_RTSX_PCI is not set
|
||||||
# CONFIG_HABANA_AI is not set
|
# CONFIG_HABANA_AI is not set
|
||||||
# CONFIG_UACCE is not set
|
# CONFIG_UACCE is not set
|
||||||
# CONFIG_PVPANIC is not set
|
CONFIG_PVPANIC=y
|
||||||
|
CONFIG_PVPANIC_PCI=y
|
||||||
# CONFIG_GP_PCI1XXXX is not set
|
# CONFIG_GP_PCI1XXXX is not set
|
||||||
# end of Misc devices
|
# end of Misc devices
|
||||||
|
|
||||||
@@ -1576,6 +1587,7 @@ CONFIG_HW_CONSOLE=y
|
|||||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||||
CONFIG_UNIX98_PTYS=y
|
CONFIG_UNIX98_PTYS=y
|
||||||
# CONFIG_LEGACY_PTYS is not set
|
# CONFIG_LEGACY_PTYS is not set
|
||||||
|
# CONFIG_LEGACY_TIOCSTI is not set
|
||||||
# CONFIG_LDISC_AUTOLOAD is not set
|
# CONFIG_LDISC_AUTOLOAD is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1651,8 +1663,6 @@ CONFIG_DEVMEM=y
|
|||||||
CONFIG_DEVPORT=y
|
CONFIG_DEVPORT=y
|
||||||
# CONFIG_TCG_TPM is not set
|
# CONFIG_TCG_TPM is not set
|
||||||
# CONFIG_XILLYBUS is not set
|
# CONFIG_XILLYBUS is not set
|
||||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
|
||||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
|
||||||
# end of Character devices
|
# end of Character devices
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1741,6 +1751,7 @@ CONFIG_GPIO_PL061=y
|
|||||||
# Virtual GPIO drivers
|
# Virtual GPIO drivers
|
||||||
#
|
#
|
||||||
# CONFIG_GPIO_AGGREGATOR is not set
|
# CONFIG_GPIO_AGGREGATOR is not set
|
||||||
|
# CONFIG_GPIO_LATCH is not set
|
||||||
# CONFIG_GPIO_MOCKUP is not set
|
# CONFIG_GPIO_MOCKUP is not set
|
||||||
# CONFIG_GPIO_VIRTIO is not set
|
# CONFIG_GPIO_VIRTIO is not set
|
||||||
# CONFIG_GPIO_SIM is not set
|
# CONFIG_GPIO_SIM is not set
|
||||||
@@ -2158,9 +2169,10 @@ CONFIG_UIO_DMEM_GENIRQ=y
|
|||||||
# CONFIG_UIO_PRUSS is not set
|
# CONFIG_UIO_PRUSS is not set
|
||||||
# CONFIG_UIO_MF624 is not set
|
# CONFIG_UIO_MF624 is not set
|
||||||
CONFIG_VFIO=y
|
CONFIG_VFIO=y
|
||||||
|
CONFIG_VFIO_CONTAINER=y
|
||||||
CONFIG_VFIO_IOMMU_TYPE1=y
|
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||||
CONFIG_VFIO_VIRQFD=y
|
|
||||||
# CONFIG_VFIO_NOIOMMU is not set
|
# CONFIG_VFIO_NOIOMMU is not set
|
||||||
|
CONFIG_VFIO_VIRQFD=y
|
||||||
CONFIG_VFIO_PCI_CORE=y
|
CONFIG_VFIO_PCI_CORE=y
|
||||||
CONFIG_VFIO_PCI_MMAP=y
|
CONFIG_VFIO_PCI_MMAP=y
|
||||||
CONFIG_VFIO_PCI_INTX=y
|
CONFIG_VFIO_PCI_INTX=y
|
||||||
@@ -2259,6 +2271,7 @@ CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
|
|||||||
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
||||||
CONFIG_OF_IOMMU=y
|
CONFIG_OF_IOMMU=y
|
||||||
CONFIG_IOMMU_DMA=y
|
CONFIG_IOMMU_DMA=y
|
||||||
|
# CONFIG_IOMMUFD is not set
|
||||||
# CONFIG_ARM_SMMU is not set
|
# CONFIG_ARM_SMMU is not set
|
||||||
# CONFIG_ARM_SMMU_V3 is not set
|
# CONFIG_ARM_SMMU_V3 is not set
|
||||||
CONFIG_VIRTIO_IOMMU=y
|
CONFIG_VIRTIO_IOMMU=y
|
||||||
@@ -2395,6 +2408,7 @@ CONFIG_ARM_PMU_ACPI=y
|
|||||||
# CONFIG_HISI_PMU is not set
|
# CONFIG_HISI_PMU is not set
|
||||||
# CONFIG_HISI_PCIE_PMU is not set
|
# CONFIG_HISI_PCIE_PMU is not set
|
||||||
# CONFIG_HNS3_PMU is not set
|
# CONFIG_HNS3_PMU is not set
|
||||||
|
# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set
|
||||||
# end of Performance monitor support
|
# end of Performance monitor support
|
||||||
|
|
||||||
CONFIG_RAS=y
|
CONFIG_RAS=y
|
||||||
@@ -2570,8 +2584,10 @@ CONFIG_SQUASHFS=y
|
|||||||
CONFIG_SQUASHFS_FILE_CACHE=y
|
CONFIG_SQUASHFS_FILE_CACHE=y
|
||||||
# CONFIG_SQUASHFS_FILE_DIRECT is not set
|
# CONFIG_SQUASHFS_FILE_DIRECT is not set
|
||||||
CONFIG_SQUASHFS_DECOMP_SINGLE=y
|
CONFIG_SQUASHFS_DECOMP_SINGLE=y
|
||||||
# CONFIG_SQUASHFS_DECOMP_MULTI is not set
|
# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
|
||||||
# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
|
CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y
|
||||||
|
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
|
||||||
|
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set
|
||||||
# CONFIG_SQUASHFS_XATTR is not set
|
# CONFIG_SQUASHFS_XATTR is not set
|
||||||
CONFIG_SQUASHFS_ZLIB=y
|
CONFIG_SQUASHFS_ZLIB=y
|
||||||
# CONFIG_SQUASHFS_LZ4 is not set
|
# CONFIG_SQUASHFS_LZ4 is not set
|
||||||
@@ -2710,7 +2726,6 @@ CONFIG_CRYPTO_MANAGER2=y
|
|||||||
# CONFIG_CRYPTO_USER is not set
|
# CONFIG_CRYPTO_USER is not set
|
||||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||||
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
||||||
CONFIG_CRYPTO_GF128MUL=y
|
|
||||||
CONFIG_CRYPTO_NULL=y
|
CONFIG_CRYPTO_NULL=y
|
||||||
CONFIG_CRYPTO_NULL2=y
|
CONFIG_CRYPTO_NULL2=y
|
||||||
# CONFIG_CRYPTO_PCRYPT is not set
|
# CONFIG_CRYPTO_PCRYPT is not set
|
||||||
@@ -2872,6 +2887,8 @@ CONFIG_CRYPTO_USER_API_RNG=y
|
|||||||
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
|
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
|
||||||
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
|
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
|
||||||
# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set
|
# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set
|
||||||
|
# CONFIG_CRYPTO_SM4_ARM64_CE_CCM is not set
|
||||||
|
# CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set
|
||||||
# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set
|
# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set
|
||||||
# end of Accelerated Cryptographic Algorithms for CPU (arm64)
|
# end of Accelerated Cryptographic Algorithms for CPU (arm64)
|
||||||
|
|
||||||
@@ -2910,6 +2927,7 @@ CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
|
|||||||
#
|
#
|
||||||
CONFIG_CRYPTO_LIB_UTILS=y
|
CONFIG_CRYPTO_LIB_UTILS=y
|
||||||
CONFIG_CRYPTO_LIB_AES=y
|
CONFIG_CRYPTO_LIB_AES=y
|
||||||
|
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||||
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
||||||
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
||||||
@@ -3033,22 +3051,16 @@ CONFIG_SYMBOLIC_ERRNAME=y
|
|||||||
# end of printk and dmesg options
|
# end of printk and dmesg options
|
||||||
|
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
CONFIG_DEBUG_MISC=y
|
# CONFIG_DEBUG_MISC is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Compile-time checks and compiler options
|
# Compile-time checks and compiler options
|
||||||
#
|
#
|
||||||
CONFIG_DEBUG_INFO=y
|
|
||||||
CONFIG_AS_HAS_NON_CONST_LEB128=y
|
CONFIG_AS_HAS_NON_CONST_LEB128=y
|
||||||
# CONFIG_DEBUG_INFO_NONE is not set
|
CONFIG_DEBUG_INFO_NONE=y
|
||||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
|
||||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
|
||||||
# CONFIG_DEBUG_INFO_COMPRESSED is not set
|
|
||||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
|
||||||
# CONFIG_DEBUG_INFO_BTF is not set
|
|
||||||
# CONFIG_GDB_SCRIPTS is not set
|
|
||||||
CONFIG_FRAME_WARN=2048
|
CONFIG_FRAME_WARN=2048
|
||||||
CONFIG_STRIP_ASM_SYMS=y
|
CONFIG_STRIP_ASM_SYMS=y
|
||||||
# CONFIG_READABLE_ASM is not set
|
# CONFIG_READABLE_ASM is not set
|
||||||
@@ -3206,7 +3218,7 @@ CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0
|
|||||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
|
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||||
@@ -3245,7 +3257,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
|||||||
# CONFIG_TEST_HEXDUMP is not set
|
# CONFIG_TEST_HEXDUMP is not set
|
||||||
# CONFIG_STRING_SELFTEST is not set
|
# CONFIG_STRING_SELFTEST is not set
|
||||||
# CONFIG_TEST_STRING_HELPERS is not set
|
# CONFIG_TEST_STRING_HELPERS is not set
|
||||||
# CONFIG_TEST_STRSCPY is not set
|
|
||||||
# CONFIG_TEST_KSTRTOX is not set
|
# CONFIG_TEST_KSTRTOX is not set
|
||||||
# CONFIG_TEST_PRINTF is not set
|
# CONFIG_TEST_PRINTF is not set
|
||||||
# CONFIG_TEST_SCANF is not set
|
# CONFIG_TEST_SCANF is not set
|
||||||
@@ -3254,7 +3265,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
|||||||
# CONFIG_TEST_XARRAY is not set
|
# CONFIG_TEST_XARRAY is not set
|
||||||
# CONFIG_TEST_MAPLE_TREE is not set
|
# CONFIG_TEST_MAPLE_TREE is not set
|
||||||
# CONFIG_TEST_RHASHTABLE is not set
|
# CONFIG_TEST_RHASHTABLE is not set
|
||||||
# CONFIG_TEST_SIPHASH is not set
|
|
||||||
# CONFIG_TEST_IDA is not set
|
# CONFIG_TEST_IDA is not set
|
||||||
# CONFIG_FIND_BIT_BENCHMARK is not set
|
# CONFIG_FIND_BIT_BENCHMARK is not set
|
||||||
# CONFIG_TEST_FIRMWARE is not set
|
# CONFIG_TEST_FIRMWARE is not set
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Linux/x86 6.1.6 Kernel Configuration
|
# Linux/x86 6.2.0 Kernel Configuration
|
||||||
#
|
#
|
||||||
CONFIG_CC_VERSION_TEXT="gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4)"
|
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
|
||||||
CONFIG_CC_IS_GCC=y
|
CONFIG_CC_IS_GCC=y
|
||||||
CONFIG_GCC_VERSION=120201
|
CONFIG_GCC_VERSION=110300
|
||||||
CONFIG_CLANG_VERSION=0
|
CONFIG_CLANG_VERSION=0
|
||||||
CONFIG_AS_IS_GNU=y
|
CONFIG_AS_IS_GNU=y
|
||||||
CONFIG_AS_VERSION=23700
|
CONFIG_AS_VERSION=23800
|
||||||
CONFIG_LD_IS_BFD=y
|
CONFIG_LD_IS_BFD=y
|
||||||
CONFIG_LD_VERSION=23700
|
CONFIG_LD_VERSION=23800
|
||||||
CONFIG_LLD_VERSION=0
|
CONFIG_LLD_VERSION=0
|
||||||
CONFIG_RUST_IS_AVAILABLE=y
|
|
||||||
CONFIG_CC_CAN_LINK=y
|
CONFIG_CC_CAN_LINK=y
|
||||||
|
CONFIG_CC_CAN_LINK_STATIC=y
|
||||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||||
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
|
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
|
||||||
CONFIG_CC_HAS_ASM_INLINE=y
|
CONFIG_CC_HAS_ASM_INLINE=y
|
||||||
@@ -70,7 +70,6 @@ CONFIG_HARDIRQS_SW_RESEND=y
|
|||||||
CONFIG_IRQ_DOMAIN=y
|
CONFIG_IRQ_DOMAIN=y
|
||||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||||
CONFIG_GENERIC_MSI_IRQ=y
|
CONFIG_GENERIC_MSI_IRQ=y
|
||||||
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
|
|
||||||
CONFIG_IRQ_MSI_IOMMU=y
|
CONFIG_IRQ_MSI_IOMMU=y
|
||||||
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
|
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
|
||||||
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
|
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
|
||||||
@@ -228,6 +227,7 @@ CONFIG_INITRAMFS_PRESERVE_MTIME=y
|
|||||||
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
||||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||||
CONFIG_LD_ORPHAN_WARN=y
|
CONFIG_LD_ORPHAN_WARN=y
|
||||||
|
CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
|
||||||
CONFIG_SYSCTL=y
|
CONFIG_SYSCTL=y
|
||||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||||
CONFIG_HAVE_PCSPKR_PLATFORM=y
|
CONFIG_HAVE_PCSPKR_PLATFORM=y
|
||||||
@@ -254,6 +254,7 @@ CONFIG_IO_URING=y
|
|||||||
CONFIG_ADVISE_SYSCALLS=y
|
CONFIG_ADVISE_SYSCALLS=y
|
||||||
CONFIG_MEMBARRIER=y
|
CONFIG_MEMBARRIER=y
|
||||||
CONFIG_KALLSYMS=y
|
CONFIG_KALLSYMS=y
|
||||||
|
# CONFIG_KALLSYMS_SELFTEST is not set
|
||||||
# CONFIG_KALLSYMS_ALL is not set
|
# CONFIG_KALLSYMS_ALL is not set
|
||||||
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
|
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
|
||||||
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
||||||
@@ -274,7 +275,6 @@ CONFIG_PERF_EVENTS=y
|
|||||||
# end of Kernel Performance Events And Counters
|
# end of Kernel Performance Events And Counters
|
||||||
|
|
||||||
# CONFIG_PROFILING is not set
|
# CONFIG_PROFILING is not set
|
||||||
# CONFIG_RUST is not set
|
|
||||||
# end of General setup
|
# end of General setup
|
||||||
|
|
||||||
CONFIG_64BIT=y
|
CONFIG_64BIT=y
|
||||||
@@ -294,7 +294,6 @@ CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
|||||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||||
CONFIG_ARCH_HAS_CPU_RELAX=y
|
CONFIG_ARCH_HAS_CPU_RELAX=y
|
||||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||||
CONFIG_ARCH_NR_GPIO=1024
|
|
||||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||||
CONFIG_AUDIT_ARCH=y
|
CONFIG_AUDIT_ARCH=y
|
||||||
CONFIG_X86_64_SMP=y
|
CONFIG_X86_64_SMP=y
|
||||||
@@ -422,7 +421,10 @@ CONFIG_X86_INTEL_TSX_MODE_OFF=y
|
|||||||
# CONFIG_X86_SGX is not set
|
# CONFIG_X86_SGX is not set
|
||||||
CONFIG_EFI=y
|
CONFIG_EFI=y
|
||||||
CONFIG_EFI_STUB=y
|
CONFIG_EFI_STUB=y
|
||||||
|
# CONFIG_EFI_HANDOVER_PROTOCOL is not set
|
||||||
# CONFIG_EFI_MIXED is not set
|
# CONFIG_EFI_MIXED is not set
|
||||||
|
# CONFIG_EFI_FAKE_MEMMAP is not set
|
||||||
|
CONFIG_EFI_RUNTIME_MAP=y
|
||||||
# CONFIG_HZ_100 is not set
|
# CONFIG_HZ_100 is not set
|
||||||
CONFIG_HZ_250=y
|
CONFIG_HZ_250=y
|
||||||
# CONFIG_HZ_300 is not set
|
# CONFIG_HZ_300 is not set
|
||||||
@@ -455,11 +457,20 @@ CONFIG_HAVE_LIVEPATCH=y
|
|||||||
|
|
||||||
CONFIG_CC_HAS_SLS=y
|
CONFIG_CC_HAS_SLS=y
|
||||||
CONFIG_CC_HAS_RETURN_THUNK=y
|
CONFIG_CC_HAS_RETURN_THUNK=y
|
||||||
|
CONFIG_CC_HAS_ENTRY_PADDING=y
|
||||||
|
CONFIG_FUNCTION_PADDING_CFI=11
|
||||||
|
CONFIG_FUNCTION_PADDING_BYTES=16
|
||||||
|
CONFIG_CALL_PADDING=y
|
||||||
|
CONFIG_HAVE_CALL_THUNKS=y
|
||||||
|
CONFIG_CALL_THUNKS=y
|
||||||
|
CONFIG_PREFIX_SYMBOLS=y
|
||||||
CONFIG_SPECULATION_MITIGATIONS=y
|
CONFIG_SPECULATION_MITIGATIONS=y
|
||||||
CONFIG_PAGE_TABLE_ISOLATION=y
|
CONFIG_PAGE_TABLE_ISOLATION=y
|
||||||
CONFIG_RETPOLINE=y
|
CONFIG_RETPOLINE=y
|
||||||
CONFIG_RETHUNK=y
|
CONFIG_RETHUNK=y
|
||||||
CONFIG_CPU_UNRET_ENTRY=y
|
CONFIG_CPU_UNRET_ENTRY=y
|
||||||
|
CONFIG_CALL_DEPTH_TRACKING=y
|
||||||
|
# CONFIG_CALL_THUNKS_DEBUG is not set
|
||||||
CONFIG_CPU_IBPB_ENTRY=y
|
CONFIG_CPU_IBPB_ENTRY=y
|
||||||
CONFIG_CPU_IBRS_ENTRY=y
|
CONFIG_CPU_IBRS_ENTRY=y
|
||||||
# CONFIG_SLS is not set
|
# CONFIG_SLS is not set
|
||||||
@@ -533,6 +544,7 @@ CONFIG_HAVE_ACPI_APEI_NMI=y
|
|||||||
# CONFIG_ACPI_CONFIGFS is not set
|
# CONFIG_ACPI_CONFIGFS is not set
|
||||||
# CONFIG_ACPI_PFRUT is not set
|
# CONFIG_ACPI_PFRUT is not set
|
||||||
# CONFIG_ACPI_PCC is not set
|
# CONFIG_ACPI_PCC is not set
|
||||||
|
# CONFIG_ACPI_FFH is not set
|
||||||
# CONFIG_PMIC_OPREGION is not set
|
# CONFIG_PMIC_OPREGION is not set
|
||||||
CONFIG_ACPI_VIOT=y
|
CONFIG_ACPI_VIOT=y
|
||||||
# CONFIG_ACPI_PRMT is not set
|
# CONFIG_ACPI_PRMT is not set
|
||||||
@@ -628,6 +640,7 @@ CONFIG_KVM=y
|
|||||||
# CONFIG_KVM_WERROR is not set
|
# CONFIG_KVM_WERROR is not set
|
||||||
CONFIG_KVM_INTEL=y
|
CONFIG_KVM_INTEL=y
|
||||||
# CONFIG_KVM_AMD is not set
|
# CONFIG_KVM_AMD is not set
|
||||||
|
CONFIG_KVM_SMM=y
|
||||||
# CONFIG_KVM_XEN is not set
|
# CONFIG_KVM_XEN is not set
|
||||||
CONFIG_AS_AVX512=y
|
CONFIG_AS_AVX512=y
|
||||||
CONFIG_AS_SHA1_NI=y
|
CONFIG_AS_SHA1_NI=y
|
||||||
@@ -684,6 +697,7 @@ CONFIG_MMU_GATHER_TABLE_FREE=y
|
|||||||
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
||||||
CONFIG_MMU_GATHER_MERGE_VMAS=y
|
CONFIG_MMU_GATHER_MERGE_VMAS=y
|
||||||
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
||||||
|
CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y
|
||||||
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
||||||
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
||||||
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
||||||
@@ -765,6 +779,9 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
|
|||||||
# end of GCOV-based kernel profiling
|
# end of GCOV-based kernel profiling
|
||||||
|
|
||||||
CONFIG_HAVE_GCC_PLUGINS=y
|
CONFIG_HAVE_GCC_PLUGINS=y
|
||||||
|
CONFIG_FUNCTION_ALIGNMENT_4B=y
|
||||||
|
CONFIG_FUNCTION_ALIGNMENT_16B=y
|
||||||
|
CONFIG_FUNCTION_ALIGNMENT=16
|
||||||
# end of General architecture-dependent options
|
# end of General architecture-dependent options
|
||||||
|
|
||||||
CONFIG_RT_MUTEXES=y
|
CONFIG_RT_MUTEXES=y
|
||||||
@@ -882,7 +899,8 @@ CONFIG_ZSMALLOC_STAT=y
|
|||||||
#
|
#
|
||||||
# CONFIG_SLAB is not set
|
# CONFIG_SLAB is not set
|
||||||
CONFIG_SLUB=y
|
CONFIG_SLUB=y
|
||||||
# CONFIG_SLOB is not set
|
# CONFIG_SLOB_DEPRECATED is not set
|
||||||
|
# CONFIG_SLUB_TINY is not set
|
||||||
CONFIG_SLAB_MERGE_DEFAULT=y
|
CONFIG_SLAB_MERGE_DEFAULT=y
|
||||||
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
||||||
CONFIG_SLAB_FREELIST_HARDENED=y
|
CONFIG_SLAB_FREELIST_HARDENED=y
|
||||||
@@ -957,7 +975,6 @@ CONFIG_SECRETMEM=y
|
|||||||
CONFIG_USERFAULTFD=y
|
CONFIG_USERFAULTFD=y
|
||||||
CONFIG_HAVE_ARCH_USERFAULTFD_WP=y
|
CONFIG_HAVE_ARCH_USERFAULTFD_WP=y
|
||||||
CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y
|
CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y
|
||||||
CONFIG_PTE_MARKER=y
|
|
||||||
CONFIG_PTE_MARKER_UFFD_WP=y
|
CONFIG_PTE_MARKER_UFFD_WP=y
|
||||||
# CONFIG_LRU_GEN is not set
|
# CONFIG_LRU_GEN is not set
|
||||||
|
|
||||||
@@ -1122,7 +1139,6 @@ CONFIG_PCIE_PME=y
|
|||||||
# CONFIG_PCIE_DPC is not set
|
# CONFIG_PCIE_DPC is not set
|
||||||
# CONFIG_PCIE_PTM is not set
|
# CONFIG_PCIE_PTM is not set
|
||||||
CONFIG_PCI_MSI=y
|
CONFIG_PCI_MSI=y
|
||||||
CONFIG_PCI_MSI_IRQ_DOMAIN=y
|
|
||||||
CONFIG_PCI_QUIRKS=y
|
CONFIG_PCI_QUIRKS=y
|
||||||
CONFIG_PCI_DEBUG=y
|
CONFIG_PCI_DEBUG=y
|
||||||
CONFIG_PCI_STUB=y
|
CONFIG_PCI_STUB=y
|
||||||
@@ -1251,11 +1267,8 @@ CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
|
|||||||
# EFI (Extensible Firmware Interface) Support
|
# EFI (Extensible Firmware Interface) Support
|
||||||
#
|
#
|
||||||
CONFIG_EFI_ESRT=y
|
CONFIG_EFI_ESRT=y
|
||||||
CONFIG_EFI_RUNTIME_MAP=y
|
|
||||||
# CONFIG_EFI_FAKE_MEMMAP is not set
|
|
||||||
CONFIG_EFI_DXE_MEM_ATTRIBUTES=y
|
CONFIG_EFI_DXE_MEM_ATTRIBUTES=y
|
||||||
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
||||||
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
|
||||||
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
||||||
# CONFIG_EFI_CAPSULE_LOADER is not set
|
# CONFIG_EFI_CAPSULE_LOADER is not set
|
||||||
# CONFIG_EFI_TEST is not set
|
# CONFIG_EFI_TEST is not set
|
||||||
@@ -1296,6 +1309,7 @@ CONFIG_ZRAM_DEF_COMP_LZORLE=y
|
|||||||
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
||||||
# CONFIG_ZRAM_WRITEBACK is not set
|
# CONFIG_ZRAM_WRITEBACK is not set
|
||||||
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
||||||
|
# CONFIG_ZRAM_MULTI_COMP is not set
|
||||||
CONFIG_BLK_DEV_LOOP=y
|
CONFIG_BLK_DEV_LOOP=y
|
||||||
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
||||||
# CONFIG_BLK_DEV_DRBD is not set
|
# CONFIG_BLK_DEV_DRBD is not set
|
||||||
@@ -1364,7 +1378,8 @@ CONFIG_NVME_MULTIPATH=y
|
|||||||
# CONFIG_MISC_RTSX_PCI is not set
|
# CONFIG_MISC_RTSX_PCI is not set
|
||||||
# CONFIG_HABANA_AI is not set
|
# CONFIG_HABANA_AI is not set
|
||||||
# CONFIG_UACCE is not set
|
# CONFIG_UACCE is not set
|
||||||
# CONFIG_PVPANIC is not set
|
CONFIG_PVPANIC=y
|
||||||
|
CONFIG_PVPANIC_PCI=y
|
||||||
# CONFIG_GP_PCI1XXXX is not set
|
# CONFIG_GP_PCI1XXXX is not set
|
||||||
# end of Misc devices
|
# end of Misc devices
|
||||||
|
|
||||||
@@ -1550,6 +1565,7 @@ CONFIG_HW_CONSOLE=y
|
|||||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||||
CONFIG_UNIX98_PTYS=y
|
CONFIG_UNIX98_PTYS=y
|
||||||
# CONFIG_LEGACY_PTYS is not set
|
# CONFIG_LEGACY_PTYS is not set
|
||||||
|
# CONFIG_LEGACY_TIOCSTI is not set
|
||||||
# CONFIG_LDISC_AUTOLOAD is not set
|
# CONFIG_LDISC_AUTOLOAD is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1624,8 +1640,6 @@ CONFIG_HANGCHECK_TIMER=y
|
|||||||
# CONFIG_TCG_TPM is not set
|
# CONFIG_TCG_TPM is not set
|
||||||
# CONFIG_TELCLOCK is not set
|
# CONFIG_TELCLOCK is not set
|
||||||
# CONFIG_XILLYBUS is not set
|
# CONFIG_XILLYBUS is not set
|
||||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
|
||||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
|
||||||
# end of Character devices
|
# end of Character devices
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1674,6 +1688,7 @@ CONFIG_GPIOLIB_IRQCHIP=y
|
|||||||
CONFIG_GPIO_SYSFS=y
|
CONFIG_GPIO_SYSFS=y
|
||||||
CONFIG_GPIO_CDEV=y
|
CONFIG_GPIO_CDEV=y
|
||||||
CONFIG_GPIO_CDEV_V1=y
|
CONFIG_GPIO_CDEV_V1=y
|
||||||
|
CONFIG_GPIO_IDIO_16=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Memory mapped GPIO drivers
|
# Memory mapped GPIO drivers
|
||||||
@@ -1717,6 +1732,7 @@ CONFIG_GPIO_PCI_IDIO_16=y
|
|||||||
# Virtual GPIO drivers
|
# Virtual GPIO drivers
|
||||||
#
|
#
|
||||||
# CONFIG_GPIO_AGGREGATOR is not set
|
# CONFIG_GPIO_AGGREGATOR is not set
|
||||||
|
# CONFIG_GPIO_LATCH is not set
|
||||||
# CONFIG_GPIO_MOCKUP is not set
|
# CONFIG_GPIO_MOCKUP is not set
|
||||||
# CONFIG_GPIO_VIRTIO is not set
|
# CONFIG_GPIO_VIRTIO is not set
|
||||||
# CONFIG_GPIO_SIM is not set
|
# CONFIG_GPIO_SIM is not set
|
||||||
@@ -1784,6 +1800,7 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0
|
|||||||
# CONFIG_MAX63XX_WATCHDOG is not set
|
# CONFIG_MAX63XX_WATCHDOG is not set
|
||||||
# CONFIG_ACQUIRE_WDT is not set
|
# CONFIG_ACQUIRE_WDT is not set
|
||||||
# CONFIG_ADVANTECH_WDT is not set
|
# CONFIG_ADVANTECH_WDT is not set
|
||||||
|
# CONFIG_ADVANTECH_EC_WDT is not set
|
||||||
# CONFIG_ALIM1535_WDT is not set
|
# CONFIG_ALIM1535_WDT is not set
|
||||||
# CONFIG_ALIM7101_WDT is not set
|
# CONFIG_ALIM7101_WDT is not set
|
||||||
# CONFIG_EBC_C384_WDT is not set
|
# CONFIG_EBC_C384_WDT is not set
|
||||||
@@ -2124,9 +2141,10 @@ CONFIG_UIO_DMEM_GENIRQ=y
|
|||||||
# CONFIG_UIO_MF624 is not set
|
# CONFIG_UIO_MF624 is not set
|
||||||
# CONFIG_UIO_HV_GENERIC is not set
|
# CONFIG_UIO_HV_GENERIC is not set
|
||||||
CONFIG_VFIO=y
|
CONFIG_VFIO=y
|
||||||
|
CONFIG_VFIO_CONTAINER=y
|
||||||
CONFIG_VFIO_IOMMU_TYPE1=y
|
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||||
CONFIG_VFIO_VIRQFD=y
|
|
||||||
# CONFIG_VFIO_NOIOMMU is not set
|
# CONFIG_VFIO_NOIOMMU is not set
|
||||||
|
CONFIG_VFIO_VIRQFD=y
|
||||||
CONFIG_VFIO_PCI_CORE=y
|
CONFIG_VFIO_PCI_CORE=y
|
||||||
CONFIG_VFIO_PCI_MMAP=y
|
CONFIG_VFIO_PCI_MMAP=y
|
||||||
CONFIG_VFIO_PCI_INTX=y
|
CONFIG_VFIO_PCI_INTX=y
|
||||||
@@ -2202,6 +2220,7 @@ CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
|
|||||||
CONFIG_IOMMU_DMA=y
|
CONFIG_IOMMU_DMA=y
|
||||||
# CONFIG_AMD_IOMMU is not set
|
# CONFIG_AMD_IOMMU is not set
|
||||||
# CONFIG_INTEL_IOMMU is not set
|
# CONFIG_INTEL_IOMMU is not set
|
||||||
|
# CONFIG_IOMMUFD is not set
|
||||||
# CONFIG_IRQ_REMAP is not set
|
# CONFIG_IRQ_REMAP is not set
|
||||||
CONFIG_HYPERV_IOMMU=y
|
CONFIG_HYPERV_IOMMU=y
|
||||||
CONFIG_VIRTIO_IOMMU=y
|
CONFIG_VIRTIO_IOMMU=y
|
||||||
@@ -2544,12 +2563,7 @@ CONFIG_LSM="yama,loadpin,safesetid,integrity"
|
|||||||
#
|
#
|
||||||
# Memory initialization
|
# Memory initialization
|
||||||
#
|
#
|
||||||
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
|
CONFIG_INIT_STACK_NONE=y
|
||||||
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y
|
|
||||||
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
|
|
||||||
# CONFIG_INIT_STACK_NONE is not set
|
|
||||||
# CONFIG_INIT_STACK_ALL_PATTERN is not set
|
|
||||||
CONFIG_INIT_STACK_ALL_ZERO=y
|
|
||||||
# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
|
# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
|
||||||
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
|
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
|
||||||
CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
|
CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
|
||||||
@@ -2585,7 +2599,6 @@ CONFIG_CRYPTO_MANAGER2=y
|
|||||||
# CONFIG_CRYPTO_USER is not set
|
# CONFIG_CRYPTO_USER is not set
|
||||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||||
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
||||||
CONFIG_CRYPTO_GF128MUL=y
|
|
||||||
CONFIG_CRYPTO_NULL=y
|
CONFIG_CRYPTO_NULL=y
|
||||||
CONFIG_CRYPTO_NULL2=y
|
CONFIG_CRYPTO_NULL2=y
|
||||||
# CONFIG_CRYPTO_PCRYPT is not set
|
# CONFIG_CRYPTO_PCRYPT is not set
|
||||||
@@ -2795,6 +2808,7 @@ CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
|
|||||||
#
|
#
|
||||||
CONFIG_CRYPTO_LIB_UTILS=y
|
CONFIG_CRYPTO_LIB_UTILS=y
|
||||||
CONFIG_CRYPTO_LIB_AES=y
|
CONFIG_CRYPTO_LIB_AES=y
|
||||||
|
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||||
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
||||||
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
||||||
@@ -2882,6 +2896,7 @@ CONFIG_FONT_8x16=y
|
|||||||
CONFIG_SG_POOL=y
|
CONFIG_SG_POOL=y
|
||||||
CONFIG_ARCH_HAS_PMEM_API=y
|
CONFIG_ARCH_HAS_PMEM_API=y
|
||||||
CONFIG_MEMREGION=y
|
CONFIG_MEMREGION=y
|
||||||
|
CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION=y
|
||||||
CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
|
CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
|
||||||
CONFIG_ARCH_HAS_COPY_MC=y
|
CONFIG_ARCH_HAS_COPY_MC=y
|
||||||
CONFIG_ARCH_STACKWALK=y
|
CONFIG_ARCH_STACKWALK=y
|
||||||
@@ -2910,22 +2925,16 @@ CONFIG_SYMBOLIC_ERRNAME=y
|
|||||||
# end of printk and dmesg options
|
# end of printk and dmesg options
|
||||||
|
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
CONFIG_DEBUG_MISC=y
|
# CONFIG_DEBUG_MISC is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Compile-time checks and compiler options
|
# Compile-time checks and compiler options
|
||||||
#
|
#
|
||||||
CONFIG_DEBUG_INFO=y
|
|
||||||
CONFIG_AS_HAS_NON_CONST_LEB128=y
|
CONFIG_AS_HAS_NON_CONST_LEB128=y
|
||||||
# CONFIG_DEBUG_INFO_NONE is not set
|
CONFIG_DEBUG_INFO_NONE=y
|
||||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
|
||||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
|
||||||
# CONFIG_DEBUG_INFO_COMPRESSED is not set
|
|
||||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
|
||||||
# CONFIG_DEBUG_INFO_BTF is not set
|
|
||||||
# CONFIG_GDB_SCRIPTS is not set
|
|
||||||
CONFIG_FRAME_WARN=2048
|
CONFIG_FRAME_WARN=2048
|
||||||
CONFIG_STRIP_ASM_SYMS=y
|
CONFIG_STRIP_ASM_SYMS=y
|
||||||
# CONFIG_READABLE_ASM is not set
|
# CONFIG_READABLE_ASM is not set
|
||||||
@@ -3098,6 +3107,7 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
|||||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||||
CONFIG_HAVE_FENTRY=y
|
CONFIG_HAVE_FENTRY=y
|
||||||
CONFIG_HAVE_OBJTOOL_MCOUNT=y
|
CONFIG_HAVE_OBJTOOL_MCOUNT=y
|
||||||
|
CONFIG_HAVE_OBJTOOL_NOP_MCOUNT=y
|
||||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||||
CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
|
CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
|
||||||
CONFIG_TRACING_SUPPORT=y
|
CONFIG_TRACING_SUPPORT=y
|
||||||
@@ -3157,7 +3167,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
|||||||
# CONFIG_TEST_HEXDUMP is not set
|
# CONFIG_TEST_HEXDUMP is not set
|
||||||
# CONFIG_STRING_SELFTEST is not set
|
# CONFIG_STRING_SELFTEST is not set
|
||||||
# CONFIG_TEST_STRING_HELPERS is not set
|
# CONFIG_TEST_STRING_HELPERS is not set
|
||||||
# CONFIG_TEST_STRSCPY is not set
|
|
||||||
# CONFIG_TEST_KSTRTOX is not set
|
# CONFIG_TEST_KSTRTOX is not set
|
||||||
# CONFIG_TEST_PRINTF is not set
|
# CONFIG_TEST_PRINTF is not set
|
||||||
# CONFIG_TEST_SCANF is not set
|
# CONFIG_TEST_SCANF is not set
|
||||||
@@ -3166,7 +3175,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
|||||||
# CONFIG_TEST_XARRAY is not set
|
# CONFIG_TEST_XARRAY is not set
|
||||||
# CONFIG_TEST_MAPLE_TREE is not set
|
# CONFIG_TEST_MAPLE_TREE is not set
|
||||||
# CONFIG_TEST_RHASHTABLE is not set
|
# CONFIG_TEST_RHASHTABLE is not set
|
||||||
# CONFIG_TEST_SIPHASH is not set
|
|
||||||
# CONFIG_TEST_IDA is not set
|
# CONFIG_TEST_IDA is not set
|
||||||
# CONFIG_FIND_BIT_BENCHMARK is not set
|
# CONFIG_FIND_BIT_BENCHMARK is not set
|
||||||
# CONFIG_TEST_FIRMWARE is not set
|
# CONFIG_TEST_FIRMWARE is not set
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set -x
|
|||||||
|
|
||||||
rm -f /tmp/ubuntu-cloudinit.img
|
rm -f /tmp/ubuntu-cloudinit.img
|
||||||
mkdosfs -n CIDATA -C /tmp/ubuntu-cloudinit.img 8192
|
mkdosfs -n CIDATA -C /tmp/ubuntu-cloudinit.img 8192
|
||||||
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/user-data ::
|
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/user-data ::
|
||||||
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/meta-data ::
|
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/meta-data ::
|
||||||
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/network-config ::
|
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/network-config ::
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
CLI_NAME="Cloud Hypervisor"
|
CLI_NAME="Cloud Hypervisor"
|
||||||
|
|
||||||
CTR_IMAGE_TAG="cloudhypervisor/dev"
|
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
|
||||||
CTR_IMAGE_VERSION="20230123-0"
|
CTR_IMAGE_VERSION="20230804-0"
|
||||||
CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
|
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
|
||||||
|
|
||||||
DOCKER_RUNTIME="docker"
|
DOCKER_RUNTIME="docker"
|
||||||
|
|
||||||
@@ -172,7 +172,11 @@ process_volumes_args() {
|
|||||||
cmd_help() {
|
cmd_help() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "Cloud Hypervisor $(basename "$0")"
|
echo "Cloud Hypervisor $(basename "$0")"
|
||||||
echo "Usage: $(basename "$0") <command> [<command args>]"
|
echo "Usage: $(basename "$0") [flags] <command> [<command args>]"
|
||||||
|
echo ""
|
||||||
|
echo "Available flags":
|
||||||
|
echo ""
|
||||||
|
echo " --local Set the container image version being used to \"local\"."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Available commands:"
|
echo "Available commands:"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -422,7 +426,7 @@ cmd_tests() {
|
|||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env CH_LIBC="${libc}" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$integration_sgx" = true ]; then
|
if [ "$integration_sgx" = true ]; then
|
||||||
@@ -535,6 +539,7 @@ cmd_tests() {
|
|||||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||||
--env USER="root" \
|
--env USER="root" \
|
||||||
--env CH_LIBC="${libc}" \
|
--env CH_LIBC="${libc}" \
|
||||||
|
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \
|
||||||
"$CTR_IMAGE" \
|
"$CTR_IMAGE" \
|
||||||
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
|
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -95,6 +95,14 @@ update_workloads() {
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
FOCAL_OS_QCOW2_IMAGE_BACKING_FILE_NAME="focal-server-cloudimg-arm64-custom-20210929-0-backing.qcow2"
|
||||||
|
FOCAL_OS_QCOW2_BACKING_FILE_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_QCOW2_IMAGE_BACKING_FILE_NAME"
|
||||||
|
if [ ! -f "$FOCAL_OS_QCOW2_BACKING_FILE_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time qemu-img create -f qcow2 -b $FOCAL_OS_QCOW2_UNCOMPRESSED_IMAGE -F qcow2 $FOCAL_OS_QCOW2_IMAGE_BACKING_FILE_NAME
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.raw"
|
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_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_RAW_IMAGE_NAME"
|
||||||
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
|
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
|
||||||
@@ -148,7 +156,7 @@ update_workloads() {
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
# Download Cloud Hypervisor binary from its last stable release
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
LAST_RELEASE_VERSION="v26.0"
|
LAST_RELEASE_VERSION="v30.0"
|
||||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
||||||
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
@@ -225,8 +233,8 @@ fi
|
|||||||
|
|
||||||
BUILD_TARGET="aarch64-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="aarch64-unknown-linux-${CH_LIBC}"
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||||
export TARGET_CC="musl-gcc"
|
export TARGET_CC="musl-gcc"
|
||||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
@@ -240,7 +248,9 @@ 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 and ovs-dpdk rely on hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||||
|
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||||
|
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
# Run all direct kernel boot (Device Tree) test cases in mod `parallel`
|
# Run all direct kernel boot (Device Tree) test cases in mod `parallel`
|
||||||
@@ -279,4 +289,12 @@ else
|
|||||||
exit $RES
|
exit $RES
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Run tests on dbus_api
|
||||||
|
if [ $RES -eq 0 ]; then
|
||||||
|
cargo build --features "dbus_api" --all --release --target $BUILD_TARGET
|
||||||
|
export RUST_BACKTRACE=1
|
||||||
|
time cargo test "dbus_api::$test_filter" --target $BUILD_TARGET -- ${test_binary_args[*]}
|
||||||
|
RES=$?
|
||||||
|
fi
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ process_common_args "$@"
|
|||||||
test_features=""
|
test_features=""
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
test_features="--no-default-features --features mshv"
|
test_features="--features mshv"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
||||||
@@ -46,7 +46,7 @@ fi
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
# Download Cloud Hypervisor binary from its last stable release
|
# Download Cloud Hypervisor binary from its last stable release
|
||||||
LAST_RELEASE_VERSION="v26.0"
|
LAST_RELEASE_VERSION="v30.0"
|
||||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
||||||
CH_RELEASE_NAME="cloud-hypervisor-static"
|
CH_RELEASE_NAME="cloud-hypervisor-static"
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
@@ -56,26 +56,8 @@ 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"
|
||||||
|
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
|
||||||
|
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||||
SRCDIR=$PWD
|
build_custom_linux
|
||||||
pushd $WORKLOADS_DIR
|
|
||||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-6.1.6" $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
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
@@ -86,10 +68,12 @@ if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
|||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
# Test ovs-dpdk relies on hugepages
|
# Test ovs-dpdk relies on hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||||
|
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||||
|
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ process_common_args "$@"
|
|||||||
test_features=""
|
test_features=""
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
test_features="--no-default-features --features mshv"
|
test_features="--features mshv"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
||||||
@@ -45,29 +45,7 @@ if [ $? -ne 0 ]; then
|
|||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
build_custom_linux
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
|
||||||
|
|
||||||
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-6.1.6" $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}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
@@ -77,7 +55,7 @@ if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
|||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test $test_features "rate_limiter::$test_filter" -- --test-threads=1 ${test_binary_args[*]}
|
time cargo test $test_features "rate_limiter::$test_filter" -- --test-threads=1 ${test_binary_args[*]}
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ 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}" == "x86_64-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/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,45 @@ source $(dirname "$0")/test-util.sh
|
|||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
|
|
||||||
WORKLOADS_DIR="$HOME/workloads"
|
WORKLOADS_DIR="$HOME/workloads"
|
||||||
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
|
mkdir -p "$WORKLOADS_DIR"
|
||||||
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
|
||||||
|
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
||||||
|
|
||||||
|
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
|
||||||
FW="$WORKLOADS_DIR/hypervisor-fw"
|
FW="$WORKLOADS_DIR/hypervisor-fw"
|
||||||
|
if [ ! -f "$FW" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $FW_URL || exit 1
|
||||||
|
popd
|
||||||
|
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="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
||||||
|
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $FOCAL_OS_IMAGE_URL || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
|
||||||
|
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
|
||||||
|
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time qemu-img convert -p -f qcow2 -O raw $FOCAL_OS_IMAGE_NAME $FOCAL_OS_RAW_IMAGE_NAME || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
sha1sum sha1sums-x86_64 --check --ignore-missing
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "sha1sum validation of images failed, remove invalid images to fix the issue."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
popd
|
||||||
|
|
||||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
build_custom_linux
|
||||||
build_custom_linux
|
|
||||||
fi
|
|
||||||
|
|
||||||
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
|
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
|
||||||
MNT_DIR="mount_image"
|
MNT_DIR="mount_image"
|
||||||
@@ -33,7 +64,7 @@ VFIO_DIR="$WORKLOADS_DIR/vfio"
|
|||||||
VFIO_DISK_IMAGE="$WORKLOADS_DIR/vfio.img"
|
VFIO_DISK_IMAGE="$WORKLOADS_DIR/vfio.img"
|
||||||
rm -rf $VFIO_DIR $VFIO_DISK_IMAGE
|
rm -rf $VFIO_DIR $VFIO_DISK_IMAGE
|
||||||
mkdir -p $VFIO_DIR
|
mkdir -p $VFIO_DIR
|
||||||
cp $FOCAL_OS_IMAGE $VFIO_DIR
|
cp $FOCAL_OS_RAW_IMAGE $VFIO_DIR
|
||||||
cp $FW $VFIO_DIR
|
cp $FW $VFIO_DIR
|
||||||
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
||||||
|
|
||||||
@@ -45,14 +76,16 @@ TARGET_CC="musl-gcc"
|
|||||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
# We always copy a fresh version of our binary for our L2 guest.
|
# We always copy a fresh version of our binary for our L2 guest.
|
||||||
cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
|
cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
|
||||||
cp target/$BUILD_TARGET/release/ch-remote $VFIO_DIR
|
cp target/$BUILD_TARGET/release/ch-remote $VFIO_DIR
|
||||||
|
|
||||||
# test_vfio rely on hugepages
|
# test_vfio rely on hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||||
|
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||||
|
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
|||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
TARGET_CC=""
|
||||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||||
export TARGET_CC="musl-gcc"
|
export TARGET_CC="musl-gcc"
|
||||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the images are present
|
# Check if the images are present
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ process_common_args "$@"
|
|||||||
test_features=""
|
test_features=""
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
test_features="--no-default-features --features mshv"
|
test_features="--features mshv"
|
||||||
fi
|
fi
|
||||||
WIN_IMAGE_FILE="/root/workloads/windows-server-2022-amd64-2.raw"
|
WIN_IMAGE_FILE="/root/workloads/windows-server-2022-amd64-2.raw"
|
||||||
|
|
||||||
@@ -26,8 +26,8 @@ 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}" == "x86_64-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/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the images are present
|
# Check if the images are present
|
||||||
@@ -44,7 +44,7 @@ dmsetup mknodes
|
|||||||
dmsetup create windows-snapshot-base --table "0 $img_blk_size snapshot-origin /dev/mapper/windows-base"
|
dmsetup create windows-snapshot-base --table "0 $img_blk_size snapshot-origin /dev/mapper/windows-base"
|
||||||
dmsetup mknodes
|
dmsetup mknodes
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ process_common_args "$@"
|
|||||||
test_features=""
|
test_features=""
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
test_features="--no-default-features --features mshv"
|
test_features="--features mshv"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
||||||
@@ -53,6 +53,14 @@ if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
FOCAL_OS_QCOW_BACKING_FILE_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0-backing.qcow2"
|
||||||
|
FOCAL_OS_QCOW_BACKING_FILE_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_QCOW_BACKING_FILE_IMAGE_NAME"
|
||||||
|
if [ ! -f "$FOCAL_OS_QCOW_BACKING_FILE_IMAGE" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time qemu-img create -f qcow2 -b $FOCAL_OS_IMAGE -F qcow2 $FOCAL_OS_QCOW_BACKING_FILE_IMAGE_NAME
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
|
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
|
||||||
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
|
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
|
||||||
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
|
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
|
||||||
@@ -156,7 +164,7 @@ cp $VMLINUX_IMAGE $VFIO_DIR || exit 1
|
|||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
# We always copy a fresh version of our binary for our L2 guest.
|
# We always copy a fresh version of our binary for our L2 guest.
|
||||||
cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
|
cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
|
||||||
@@ -169,12 +177,17 @@ 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, ovs-dpdk and vDPA tests rely on hugepages
|
# Both test_vfio, ovs-dpdk and vDPA tests rely on hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||||
|
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||||
|
echo $PAGE_NUM | 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
|
# Update max locked memory to 'unlimited' to avoid issues with vDPA
|
||||||
ulimit -l unlimited
|
ulimit -l unlimited
|
||||||
|
|
||||||
|
# Set number of open descriptors high enough for VFIO tests to run
|
||||||
|
ulimit -n 4096
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test $test_features "common_parallel::$test_filter" -- ${test_binary_args[*]}
|
time cargo test $test_features "common_parallel::$test_filter" -- ${test_binary_args[*]}
|
||||||
RES=$?
|
RES=$?
|
||||||
@@ -187,4 +200,13 @@ if [ $RES -eq 0 ]; then
|
|||||||
RES=$?
|
RES=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Run tests on dbus_api
|
||||||
|
if [ $RES -eq 0 ]; then
|
||||||
|
cargo build --features "mshv,dbus_api" --all --release --target $BUILD_TARGET
|
||||||
|
export RUST_BACKTRACE=1
|
||||||
|
# integration tests now do not reply on build feature "dbus_api"
|
||||||
|
time cargo test $test_features "dbus_api::$test_filter" -- ${test_binary_args[*]}
|
||||||
|
RES=$?
|
||||||
|
fi
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -92,10 +92,12 @@ if [[ "${BUILD_TARGET}" == "${TEST_ARCH}-unknown-linux-musl" ]]; then
|
|||||||
CFLAGS="-I /usr/include/${TEST_ARCH}-linux-musl/ -idirafter /usr/include/"
|
CFLAGS="-I /usr/include/${TEST_ARCH}-linux-musl/ -idirafter /usr/include/"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
cargo build --features mshv --all --release --target $BUILD_TARGET
|
||||||
|
|
||||||
# setup hugepages
|
# setup hugepages
|
||||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||||
|
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||||
|
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
if [ -n "$test_filter" ]; then
|
if [ -n "$test_filter" ]; then
|
||||||
@@ -105,7 +107,12 @@ fi
|
|||||||
# Ensure that git commands can be run in this directory (for metrics report)
|
# Ensure that git commands can be run in this directory (for metrics report)
|
||||||
git config --global --add safe.directory $PWD
|
git config --global --add safe.directory $PWD
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
RUST_BACKTRACE_VALUE=`echo $RUST_BACKTRACE`
|
||||||
|
if [ -z $RUST_BACKTRACE_VALUE ];then
|
||||||
|
export RUST_BACKTRACE=1
|
||||||
|
else
|
||||||
|
echo "RUST_BACKTRACE is set to: $RUST_BACKTRACE_VALUE"
|
||||||
|
fi
|
||||||
time target/$BUILD_TARGET/release/performance-metrics ${test_binary_args[*]}
|
time target/$BUILD_TARGET/release/performance-metrics ${test_binary_args[*]}
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ BUILD_TARGET=${BUILD_TARGET-x86_64-unknown-linux-gnu}
|
|||||||
cargo_args=("")
|
cargo_args=("")
|
||||||
|
|
||||||
if [[ $hypervisor = "mshv" ]]; then
|
if [[ $hypervisor = "mshv" ]]; then
|
||||||
cargo_args+=("--no-default-features")
|
|
||||||
cargo_args+=("--features $hypervisor")
|
cargo_args+=("--features $hypervisor")
|
||||||
elif [[ $(uname -m) = "x86_64" ]]; then
|
elif [[ $(uname -m) = "x86_64" ]]; then
|
||||||
cargo_args+=("--features tdx")
|
cargo_args+=("--features tdx")
|
||||||
@@ -22,3 +21,4 @@ fi
|
|||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||||
|
cargo test --doc --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user