mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
477 Commits
v19.0
...
stable/v21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e01933c8ea | ||
|
|
c6307865eb | ||
|
|
6275d4f87e | ||
|
|
4dfe1ff77a | ||
|
|
bbda07c388 | ||
|
|
366223c9f4 | ||
|
|
375356a097 | ||
|
|
95ca79974a | ||
|
|
eb5c5f2c7f | ||
|
|
85bbf75fe8 | ||
|
|
b4566b9eab | ||
|
|
e2a8a1483f | ||
|
|
ea60d48853 | ||
|
|
658658e76c | ||
|
|
b7b3b45364 | ||
|
|
d5b4d0d951 | ||
|
|
1c18d124dc | ||
|
|
7a42ce9310 | ||
|
|
1db7718589 | ||
|
|
cf68f03ab6 | ||
|
|
4ecc778efe | ||
|
|
48ba999bd9 | ||
|
|
ef05354c81 | ||
|
|
277cfd07ba | ||
|
|
4f05b8463c | ||
|
|
c9983ff4ad | ||
|
|
714b529bb2 | ||
|
|
99bcebad74 | ||
|
|
22d86fb6d2 | ||
|
|
2eed24b4b2 | ||
|
|
be7829b752 | ||
|
|
ea2685e928 | ||
|
|
14ba3f68d3 | ||
|
|
779bc1a53a | ||
|
|
8b8daf571a | ||
|
|
482e1ca435 | ||
|
|
a61302f73f | ||
|
|
33fd0af8b3 | ||
|
|
cb243571de | ||
|
|
70f7f64e23 | ||
|
|
88952cc500 | ||
|
|
715a7d9065 | ||
|
|
1676fffaad | ||
|
|
1daef5e8c9 | ||
|
|
735658a49d | ||
|
|
b95e46565c | ||
|
|
eeba1d3ad8 | ||
|
|
271e17bd79 | ||
|
|
b9c260c0de | ||
|
|
6e78ac1837 | ||
|
|
dad5af612b | ||
|
|
101d403a6b | ||
|
|
29e3fefc3d | ||
|
|
859f72b5a5 | ||
|
|
8155be2e6b | ||
|
|
4577e5050b | ||
|
|
1952405f69 | ||
|
|
1dc913427c | ||
|
|
0a97b76c52 | ||
|
|
b204f43aae | ||
|
|
ade8d71264 | ||
|
|
92b8bdf474 | ||
|
|
84e2f6c1da | ||
|
|
e02f5c9699 | ||
|
|
2f492fbe36 | ||
|
|
c47cb868ec | ||
|
|
fb1755d85d | ||
|
|
5e1e523a90 | ||
|
|
685ca03e67 | ||
|
|
b80feb3d96 | ||
|
|
cb15ae5462 | ||
|
|
6738e45b37 | ||
|
|
c2f133990d | ||
|
|
a926bc139b | ||
|
|
5b05e0cdcd | ||
|
|
e7a2a715e0 | ||
|
|
430f72f96c | ||
|
|
901f65388a | ||
|
|
68e95d5841 | ||
|
|
c5f20c45a0 | ||
|
|
c7d1cfbd88 | ||
|
|
9c8f291b60 | ||
|
|
70af81d755 | ||
|
|
8fa3864ae8 | ||
|
|
221c1f1bdc | ||
|
|
3baebc1af0 | ||
|
|
2563b08ff0 | ||
|
|
f6333a39a5 | ||
|
|
936237d4d6 | ||
|
|
6408e8629e | ||
|
|
617b568f71 | ||
|
|
0fcbcea275 | ||
|
|
10d1922393 | ||
|
|
0162d73ed8 | ||
|
|
d57c49664f | ||
|
|
2f46647ecc | ||
|
|
9ef1187f4a | ||
|
|
e7db354c27 | ||
|
|
6ba5b0a83a | ||
|
|
2c59702e4a | ||
|
|
98ba347956 | ||
|
|
cd0aca4bcd | ||
|
|
f27cbb9caf | ||
|
|
e4763b47f1 | ||
|
|
7cc1643782 | ||
|
|
58501ed0a6 | ||
|
|
b72136ddb3 | ||
|
|
07756aa8fb | ||
|
|
c47ab55e99 | ||
|
|
a749063c8a | ||
|
|
cf2abd35d0 | ||
|
|
0dbff2a81d | ||
|
|
e355bb9fd4 | ||
|
|
aeaf432784 | ||
|
|
ccc9308ec1 | ||
|
|
129f708df7 | ||
|
|
542f05ebfa | ||
|
|
8e89a10db7 | ||
|
|
5283cb38db | ||
|
|
346bee48ad | ||
|
|
210a29f05c | ||
|
|
21a21ce51a | ||
|
|
877a537bf7 | ||
|
|
5a1e9c9bff | ||
|
|
a45939fb40 | ||
|
|
b85d29780f | ||
|
|
b3351e11b3 | ||
|
|
05720dbf25 | ||
|
|
d7ba8ad1fa | ||
|
|
748611752d | ||
|
|
9c5636204d | ||
|
|
fbbbd04ddf | ||
|
|
89af7dcb2b | ||
|
|
8737ca4d45 | ||
|
|
d186297dba | ||
|
|
09d6cdb185 | ||
|
|
c40c1778e5 | ||
|
|
58a2abbba2 | ||
|
|
b6159217b6 | ||
|
|
7bb828ecf2 | ||
|
|
4a47cdcebd | ||
|
|
8813456aef | ||
|
|
6c8bd1f476 | ||
|
|
6a76a6772d | ||
|
|
cbc388c7e2 | ||
|
|
4773e23c77 | ||
|
|
3b0d278ba3 | ||
|
|
443b64b04f | ||
|
|
ccccc94c8a | ||
|
|
3f0a33a50f | ||
|
|
32aedddb0a | ||
|
|
fa15cf6ac3 | ||
|
|
5c12c15f26 | ||
|
|
bde81405a8 | ||
|
|
9742fa5c7c | ||
|
|
3806afdc43 | ||
|
|
c6ba188586 | ||
|
|
afe386bc13 | ||
|
|
df21e15148 | ||
|
|
2883c71911 | ||
|
|
07a78842b5 | ||
|
|
91c7590ba6 | ||
|
|
e1b0630b79 | ||
|
|
2a2cea1658 | ||
|
|
3cd02403db | ||
|
|
a9f5021005 | ||
|
|
f14d0d0191 | ||
|
|
4959434219 | ||
|
|
7444c3a0c5 | ||
|
|
35d3c1f611 | ||
|
|
be5fd7c572 | ||
|
|
39172f8b54 | ||
|
|
2bcf718028 | ||
|
|
6d047bdec6 | ||
|
|
c6e534baf7 | ||
|
|
fb2b633ada | ||
|
|
8fb64859cc | ||
|
|
254d648bb7 | ||
|
|
21b0ab106c | ||
|
|
7bce72dff3 | ||
|
|
50f5f43ae3 | ||
|
|
fd3cf761be | ||
|
|
0a04c7206d | ||
|
|
58d3d4c34e | ||
|
|
eea2907daf | ||
|
|
7b5e8a3ca8 | ||
|
|
616d01aca2 | ||
|
|
637dc53a48 | ||
|
|
4b9b52fc6f | ||
|
|
3d1cfd4d55 | ||
|
|
e1c09b66ba | ||
|
|
af770c814b | ||
|
|
a29e53e436 | ||
|
|
00bb1ea1d5 | ||
|
|
bb6c93d5df | ||
|
|
90df54a245 | ||
|
|
ca9a42ece8 | ||
|
|
2f8540da70 | ||
|
|
07bef815cc | ||
|
|
e1151482fc | ||
|
|
3e536f91eb | ||
|
|
cab0b3446f | ||
|
|
7bb343dce8 | ||
|
|
9b0fe505ca | ||
|
|
03a606c7ec | ||
|
|
c452471c4e | ||
|
|
882cdda995 | ||
|
|
788d77aee5 | ||
|
|
e08c747638 | ||
|
|
b519975fc8 | ||
|
|
348def9dfb | ||
|
|
b09cbb8493 | ||
|
|
7fc0776aac | ||
|
|
4f4eb3f6b8 | ||
|
|
8f4de45937 | ||
|
|
32dd4d10d0 | ||
|
|
27b5f8756f | ||
|
|
15358ef79d | ||
|
|
46672c384c | ||
|
|
a18b818227 | ||
|
|
0a5111b6c3 | ||
|
|
17b0f40154 | ||
|
|
8c88b10384 | ||
|
|
b0d245be70 | ||
|
|
fad29fdf1a | ||
|
|
c9374d87ac | ||
|
|
649e1fa1a6 | ||
|
|
c7725f921c | ||
|
|
82d06c0efa | ||
|
|
bc827ee3be | ||
|
|
ac25172176 | ||
|
|
c7977aa4a6 | ||
|
|
d93b7bb04e | ||
|
|
c4454f54bd | ||
|
|
580db833f0 | ||
|
|
e91409956d | ||
|
|
61ce4b8f31 | ||
|
|
154cca4170 | ||
|
|
6032e30807 | ||
|
|
7b7d720f37 | ||
|
|
d23c1abbf0 | ||
|
|
9b9015d907 | ||
|
|
60b44141b4 | ||
|
|
896a651b5c | ||
|
|
9075809494 | ||
|
|
6b23227e10 | ||
|
|
f68d63ef6c | ||
|
|
1bcb07b68b | ||
|
|
ef1ac5c670 | ||
|
|
5e7c9eaefd | ||
|
|
c4211686ab | ||
|
|
51cfffd24f | ||
|
|
e34c25cf6f | ||
|
|
366f058d61 | ||
|
|
2a312cd4fe | ||
|
|
0d7328da01 | ||
|
|
589dc77354 | ||
|
|
58d984f6b8 | ||
|
|
dd3c086a0a | ||
|
|
46953db3ca | ||
|
|
f855d9e237 | ||
|
|
ff0e92ab88 | ||
|
|
32af6f9723 | ||
|
|
9b3cab8c72 | ||
|
|
84630aa0b5 | ||
|
|
ad8ed80eb1 | ||
|
|
f035cff10f | ||
|
|
1a2b01888c | ||
|
|
94fcfa9f1f | ||
|
|
31b3871eee | ||
|
|
d8becc742c | ||
|
|
d2d6eb0591 | ||
|
|
8ee253cd3f | ||
|
|
6f49cb2860 | ||
|
|
03862314eb | ||
|
|
243b5bad65 | ||
|
|
80bbc47147 | ||
|
|
351a7b52c8 | ||
|
|
8c737793d6 | ||
|
|
419870ae45 | ||
|
|
66a2045148 | ||
|
|
5813ce0307 | ||
|
|
533e47f26b | ||
|
|
6221b6f8a1 | ||
|
|
57cc8bc6fe | ||
|
|
d3526823db | ||
|
|
608ad4894f | ||
|
|
e4dc776ea4 | ||
|
|
1fac67f648 | ||
|
|
592b8bcaaa | ||
|
|
e6e58e6d66 | ||
|
|
7c53896f11 | ||
|
|
a1f1dfddeb | ||
|
|
e2bd35f4bb | ||
|
|
b000b303e2 | ||
|
|
9260e3b273 | ||
|
|
cfdf643237 | ||
|
|
3480e69ff5 | ||
|
|
6a7a588268 | ||
|
|
932c8c9713 | ||
|
|
a4f5ad6076 | ||
|
|
be79a80361 | ||
|
|
34edb8960f | ||
|
|
83af9965fa | ||
|
|
f7e60434fa | ||
|
|
a4d8616676 | ||
|
|
38351f0d96 | ||
|
|
3587adcf5f | ||
|
|
611e71826d | ||
|
|
ed52e5c029 | ||
|
|
c8e3c1eed6 | ||
|
|
ad521fd4e4 | ||
|
|
e4cbafcd01 | ||
|
|
b81d758c41 | ||
|
|
184a3d1fb5 | ||
|
|
d3b2f2a4d9 | ||
|
|
a362e85539 | ||
|
|
9a583e6e9f | ||
|
|
a628854d9c | ||
|
|
7618cd2c2d | ||
|
|
eae4b315e4 | ||
|
|
c1a3b63112 | ||
|
|
751e76db08 | ||
|
|
d96d98d88e | ||
|
|
185f0c1bf3 | ||
|
|
e04cbb2ad4 | ||
|
|
986e43f899 | ||
|
|
a7786b4e0c | ||
|
|
def371e969 | ||
|
|
72d4d2c6f0 | ||
|
|
99467982aa | ||
|
|
6172b6aac5 | ||
|
|
9cddcc8766 | ||
|
|
d2319124f5 | ||
|
|
24fd54401d | ||
|
|
9256c41173 | ||
|
|
b1d4bcf952 | ||
|
|
8b7bfca9b0 | ||
|
|
7da69b59f7 | ||
|
|
50b6ee3947 | ||
|
|
c0ca6b5377 | ||
|
|
8c9f0e407f | ||
|
|
29f46ee470 | ||
|
|
f3e86bdf26 | ||
|
|
311dd7be50 | ||
|
|
bfd3deac7c | ||
|
|
1a35d5a017 | ||
|
|
95e63d5f44 | ||
|
|
f31d218479 | ||
|
|
ef216c37df | ||
|
|
242a7f7ab4 | ||
|
|
eec7634cd7 | ||
|
|
7ad83f1daa | ||
|
|
6c181061df | ||
|
|
99d4f77197 | ||
|
|
3c00a696b5 | ||
|
|
4f496e39a1 | ||
|
|
d92489e0a4 | ||
|
|
93647f0313 | ||
|
|
1877c723cd | ||
|
|
f51bad20bf | ||
|
|
f7da35857f | ||
|
|
5902ceb955 | ||
|
|
395929f1d4 | ||
|
|
4bd0ac6623 | ||
|
|
f917198f27 | ||
|
|
211ee1521d | ||
|
|
d0c3342c97 | ||
|
|
b4f3e1c2a1 | ||
|
|
b11a8a5ab5 | ||
|
|
436f3605e9 | ||
|
|
6cfa794f33 | ||
|
|
cc1db2ea13 | ||
|
|
fbdfc7a426 | ||
|
|
58d25b3ccc | ||
|
|
495d4eb896 | ||
|
|
6859a1694c | ||
|
|
960c7027c7 | ||
|
|
a2e02a8fff | ||
|
|
def98faf37 | ||
|
|
9d1a7e43a7 | ||
|
|
afe95e5a2a | ||
|
|
b8fee11822 | ||
|
|
e20be3e147 | ||
|
|
ec81f377b6 | ||
|
|
438be0dad5 | ||
|
|
1a5a89508b | ||
|
|
bad26133cb | ||
|
|
b881339866 | ||
|
|
0afa619d2c | ||
|
|
ae83e3b383 | ||
|
|
79e43ac534 | ||
|
|
a26ce353d3 | ||
|
|
cd9d1cf8fc | ||
|
|
a6456b50f3 | ||
|
|
7cfeefde57 | ||
|
|
f71f6da907 | ||
|
|
d4f7f42800 | ||
|
|
ca955a47ff | ||
|
|
88378d17a2 | ||
|
|
cf1c2bf0e8 | ||
|
|
e3d6e222a1 | ||
|
|
f8d9c073f0 | ||
|
|
e3c35a3579 | ||
|
|
7a4606f800 | ||
|
|
49f19e061b | ||
|
|
d33d254921 | ||
|
|
b8b0dab1ae | ||
|
|
c118d7d7d3 | ||
|
|
3059ba4305 | ||
|
|
080ce9b068 | ||
|
|
c886d71d29 | ||
|
|
4f5c179b9b | ||
|
|
fbb385834a | ||
|
|
b4fc02857f | ||
|
|
b55f009b8a | ||
|
|
b59f1d90dd | ||
|
|
a7fba8105f | ||
|
|
8b67298ad8 | ||
|
|
21706b02b8 | ||
|
|
bbc300b2cd | ||
|
|
1d095a929c | ||
|
|
5d14541924 | ||
|
|
f17addd36f | ||
|
|
b80df526e4 | ||
|
|
8c1176e33a | ||
|
|
ed5f25446a | ||
|
|
23f63262e7 | ||
|
|
455b0d12e9 | ||
|
|
3c7323230a | ||
|
|
374e1a2eca | ||
|
|
9d8315521c | ||
|
|
bc1e0361c0 | ||
|
|
8d6076653d | ||
|
|
57f063513c | ||
|
|
beb0c0707f | ||
|
|
1c2ab3e771 | ||
|
|
aaf253a2d7 | ||
|
|
bbc223b93f | ||
|
|
b5d5ffa969 | ||
|
|
93dce87cfe | ||
|
|
3dda3669b9 | ||
|
|
4c9a88db87 | ||
|
|
5dcc8cdf39 | ||
|
|
5963002cc5 | ||
|
|
f151a8602c | ||
|
|
0249e8641a | ||
|
|
7c19ae92b8 | ||
|
|
7f0e7d19a6 | ||
|
|
81b9705b10 | ||
|
|
27f7b2c2a1 | ||
|
|
76b6c62d07 | ||
|
|
7aff4decc6 | ||
|
|
bd51f3069c | ||
|
|
c8f108d2f0 | ||
|
|
e3feba287d | ||
|
|
e78c058420 | ||
|
|
70f9fea1c3 | ||
|
|
2f57d1c3f9 | ||
|
|
1311a7f178 | ||
|
|
7d7577007a | ||
|
|
84f0f332b3 | ||
|
|
e9ea9d63f8 | ||
|
|
48d4ccbfeb | ||
|
|
4ae8ee2376 | ||
|
|
8a56720b0f | ||
|
|
a3a0d26959 | ||
|
|
00bfb63607 | ||
|
|
fccd9c8829 | ||
|
|
feed0efc60 | ||
|
|
61e3f0f9e9 | ||
|
|
8df418358e | ||
|
|
2cccdc5ddd | ||
|
|
c3d6aceed1 | ||
|
|
2226207874 | ||
|
|
690bdc3448 | ||
|
|
c25bd447a1 |
3
.github/workflows/build.yaml
vendored
3
.github/workflows/build.yaml
vendored
@@ -34,6 +34,9 @@ jobs:
|
|||||||
git rev-list origin/main..$GITHUB_SHA | xargs -t -I % sh -c 'git checkout %; cargo check --all --target=${{ matrix.target }}'
|
git rev-list origin/main..$GITHUB_SHA | xargs -t -I % sh -c 'git checkout %; cargo check --all --target=${{ matrix.target }}'
|
||||||
git checkout $GITHUB_SHA
|
git checkout $GITHUB_SHA
|
||||||
|
|
||||||
|
- name: Build (default + tdx)
|
||||||
|
run: cargo rustc --bin cloud-hypervisor --features "tdx" -- -D warnings
|
||||||
|
|
||||||
- name: Build (acpi,kvm)
|
- name: Build (acpi,kvm)
|
||||||
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,kvm" -- -D warnings
|
run: cargo rustc --bin cloud-hypervisor --no-default-features --features "acpi,kvm" -- -D warnings
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/dco.yaml
vendored
2
.github/workflows/dco.yaml
vendored
@@ -15,4 +15,4 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
pip3 install -U dco-check
|
pip3 install -U dco-check
|
||||||
dco-check
|
dco-check -e "49699333+dependabot[bot]@users.noreply.github.com"
|
||||||
|
|||||||
14
.github/workflows/docker-image.yaml
vendored
14
.github/workflows/docker-image.yaml
vendored
@@ -1,9 +1,11 @@
|
|||||||
name: Cloud-Hypervisor's Docker image update
|
name: Cloud Hypervisor's Docker image update
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: main
|
branches: main
|
||||||
paths: resources/Dockerfile
|
paths: resources/Dockerfile
|
||||||
|
pull_request:
|
||||||
|
paths: resources/Dockerfile
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
@@ -19,12 +21,14 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
file: ./resources/Dockerfile
|
file: ./resources/Dockerfile
|
||||||
@@ -32,5 +36,13 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: cloudhypervisor/dev:latest
|
tags: cloudhypervisor/dev:latest
|
||||||
|
|
||||||
|
- name: Build only
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
file: ./resources/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: cloudhypervisor/dev:latest
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|||||||
2
.github/workflows/quality.yaml
vendored
2
.github/workflows/quality.yaml
vendored
@@ -55,7 +55,7 @@ jobs:
|
|||||||
run: cargo clippy --all --all-targets --no-default-features --tests --features "mshv" -- -D warnings
|
run: cargo clippy --all --all-targets --no-default-features --tests --features "mshv" -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (integration tests)
|
- name: Clippy (integration tests)
|
||||||
run: cargo clippy --all --all-targets --tests --features "integration_tests" -- -D warnings
|
run: cargo clippy --all --all-targets --tests -- -D warnings
|
||||||
|
|
||||||
- name: Check build did not modify any files
|
- name: Check build did not modify any files
|
||||||
run: test -z "$(git status --porcelain)"
|
run: test -z "$(git status --porcelain)"
|
||||||
|
|||||||
32
.github/workflows/release.yaml
vendored
32
.github/workflows/release.yaml
vendored
@@ -9,6 +9,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Code checkout
|
- name: Code checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
- name: Create release directory
|
||||||
|
run: rsync -rv --exclude=.git . ../cloud-hypervisor-${{ github.event.ref }}
|
||||||
- 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:
|
||||||
@@ -37,6 +39,13 @@ jobs:
|
|||||||
use-cross: true
|
use-cross: true
|
||||||
command: build
|
command: build
|
||||||
args: --all --release --target=aarch64-unknown-linux-musl
|
args: --all --release --target=aarch64-unknown-linux-musl
|
||||||
|
- name: Vendor
|
||||||
|
working-directory: ../cloud-hypervisor-${{ github.event.ref }}
|
||||||
|
run: |
|
||||||
|
mkdir ../vendor-cargo-home
|
||||||
|
export CARGO_HOME=$(realpath ../vendor-cargo-home)
|
||||||
|
mkdir .cargo
|
||||||
|
cargo vendor > .cargo/config.toml
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1
|
uses: actions/create-release@v1
|
||||||
@@ -47,6 +56,19 @@ jobs:
|
|||||||
release_name: ${{ github.ref }}
|
release_name: ${{ github.ref }}
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
- name: Create vendored source archive
|
||||||
|
working-directory: ../
|
||||||
|
run: tar cJf cloud-hypervisor-${{ github.event.ref }}.tar.xz cloud-hypervisor-${{ github.event.ref }}
|
||||||
|
- name: Upload cloud-hypervisor vendored source archive
|
||||||
|
id: upload-release-cloud-hypervisor-vendored-sources
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ../cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||||
|
asset_name: cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||||
|
asset_content_type: application/x-xz
|
||||||
- name: Upload cloud-hypervisor
|
- name: Upload cloud-hypervisor
|
||||||
id: upload-release-cloud-hypervisor
|
id: upload-release-cloud-hypervisor
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
@@ -77,6 +99,16 @@ jobs:
|
|||||||
asset_path: target/x86_64-unknown-linux-gnu/release/ch-remote
|
asset_path: target/x86_64-unknown-linux-gnu/release/ch-remote
|
||||||
asset_name: ch-remote
|
asset_name: ch-remote
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
- name: Upload static-ch-remote
|
||||||
|
id: upload-release-static-ch-remote
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: target/x86_64-unknown-linux-musl/release/ch-remote
|
||||||
|
asset_name: ch-remote-static
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload static AArch64 cloud-hypervisor
|
- name: Upload static AArch64 cloud-hypervisor
|
||||||
id: upload-release-static-aarch64-cloud-hypervisor
|
id: upload-release-static-aarch64-cloud-hypervisor
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
/build
|
/build
|
||||||
|
/.cargo
|
||||||
/target
|
/target
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
**/Cargo.lock
|
**/Cargo.lock
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
# Contributing to Cloud Hypervisor
|
# Contributing to Cloud Hypervisor
|
||||||
|
|
||||||
Cloud Hypervisor is an open source project licensed under the [Apache v2 License](https://opensource.org/licenses/Apache-2.0) and the [BSD 3 Clause](https://opensource.org/licenses/BSD-3-Clause) license.
|
Cloud Hypervisor is an open source project licensed under the [Apache v2
|
||||||
|
License](https://opensource.org/licenses/Apache-2.0) and the [BSD 3
|
||||||
|
Clause](https://opensource.org/licenses/BSD-3-Clause) license. Contributions
|
||||||
|
can be made under either license or both. Individual files contain details of
|
||||||
|
their licensing and changes to that file are under the same license unless the
|
||||||
|
contribution changes the license of the file. When importing code from a third
|
||||||
|
party project (e.g. Firecracker or CrosVM) please respect the license of those
|
||||||
|
projects.
|
||||||
|
|
||||||
## Coding Style
|
## Coding Style
|
||||||
|
|
||||||
|
|||||||
384
Cargo.lock
generated
384
Cargo.lock
generated
@@ -9,21 +9,6 @@ dependencies = [
|
|||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "addr2line"
|
|
||||||
version = "0.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
|
|
||||||
dependencies = [
|
|
||||||
"gimli",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.18"
|
version = "0.7.18"
|
||||||
@@ -33,20 +18,11 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.44"
|
version = "1.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
|
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -57,9 +33,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6df5aef5c5830360ce5218cecb8f018af3438af5686ae945094affc86fdec63"
|
checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arch"
|
name = "arch"
|
||||||
@@ -101,21 +77,6 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backtrace"
|
|
||||||
version = "0.3.61"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01"
|
|
||||||
dependencies = [
|
|
||||||
"addr2line",
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"miniz_oxide",
|
|
||||||
"object",
|
|
||||||
"rustc-demangle",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "1.3.3"
|
version = "1.3.3"
|
||||||
@@ -144,6 +105,7 @@ dependencies = [
|
|||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -157,9 +119,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.71"
|
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 = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -169,28 +131,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.3"
|
version = "3.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"lazy_static",
|
||||||
|
"os_str_bytes",
|
||||||
"strsim",
|
"strsim",
|
||||||
"term_size",
|
"termcolor",
|
||||||
|
"terminal_size",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"unicode-width",
|
|
||||||
"vec_map",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "19.0.0"
|
version = "21.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
"clap",
|
"clap",
|
||||||
"credibility",
|
|
||||||
"dirs 4.0.0",
|
"dirs 4.0.0",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
@@ -213,9 +175,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "210cdf933e6a81212bfabf90cd8762f471b5922e5f6b709547673ad8e04b9448"
|
checksum = "ee6b9c9389584bcba988bd0836086789b7f87ad91892d6a83d5291dbb24524b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -226,16 +188,6 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "credibility"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fae7a162fd5b462bc49704873a89950a655d44161add4be07e00e64c4c83a5bf"
|
|
||||||
dependencies = [
|
|
||||||
"failure",
|
|
||||||
"failure_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "devices"
|
name = "devices"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -318,28 +270,6 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "failure"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
|
||||||
dependencies = [
|
|
||||||
"backtrace",
|
|
||||||
"failure_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "failure_derive"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"synstructure",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdt"
|
name = "fdt"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@@ -348,21 +278,15 @@ checksum = "b643857cf70949306b81d7e92cb9d47add673868edac9863c4a49c42feaf3f1e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -370,10 +294,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hashbrown"
|
||||||
version = "0.1.19"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7a30908dbce072eca83216eab939d2290080e00ca71611b96a09e5cdce5f3fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -417,10 +347,20 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "indexmap"
|
||||||
version = "0.1.11"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
|
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -446,9 +386,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-bindings"
|
name = "kvm-bindings"
|
||||||
@@ -462,9 +402,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-ioctls"
|
name = "kvm-ioctls"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-vmm/kvm-ioctls?branch=main#d22ef1f51852dfb055da38004e1a4fed81246f81"
|
||||||
checksum = "48dc14f9047df1873cf6942caccc7431d19c3d496ca7a0d162260c4cf0f64b76"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -479,9 +418,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.103"
|
version = "0.2.112"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libssh2-sys"
|
name = "libssh2-sys"
|
||||||
@@ -542,29 +481,28 @@ version = "2.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#36e59a083e76a2449e0f58e4283d201bc72fdf13"
|
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#0a58eb1ece68e326e68365c4297d0a7c08ecd9bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.4.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
|
||||||
dependencies = [
|
|
||||||
"adler",
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-bindings"
|
name = "mshv-bindings"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#99da566389546aedb56fc3d279e01c5dbde79bce"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#b8b69b655337292037219ab765d2c94c565a076e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -576,7 +514,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "mshv-ioctls"
|
name = "mshv-ioctls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#99da566389546aedb56fc3d279e01c5dbde79bce"
|
source = "git+https://github.com/rust-vmm/mshv?branch=main#b8b69b655337292037219ab765d2c94c565a076e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mshv-bindings",
|
"mshv-bindings",
|
||||||
@@ -607,25 +545,17 @@ dependencies = [
|
|||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.26.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.67"
|
version = "0.9.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
|
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -638,6 +568,15 @@ dependencies = [
|
|||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_str_bytes"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@@ -687,15 +626,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.20"
|
version = "0.3.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
|
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet"
|
name = "pnet"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4b6d2a0409666964722368ef5fb74b9f93fac11c18bef3308693c16c6733f103"
|
checksum = "8750e073f82219c01e771133c64718d7685aef922da8a0d430a46aed05b6341a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -707,15 +646,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_base"
|
name = "pnet_base"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25488cd551a753dcaaa6fffc9f69a7610a412dd8954425bf7ffad5f7d1156fb8"
|
checksum = "8205fe084bd43a3af79b3155c19feddd62e733640498842e631a2ffe107d1538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_datalink"
|
name = "pnet_datalink"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4d1f8ab1ef6c914cf51dc5dfe0be64088ea5f3b08bbf5a31abc70356d271198"
|
checksum = "6f85aef5e52e22ff06b1b11f2eb6d52959a9e0ecad3cb3f5cc2d78cadc077f0e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork",
|
"ipnetwork",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -726,9 +665,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros"
|
name = "pnet_macros"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30490e0852e58402b8fae0d39897b08a24f493023a4d6cf56b2e30f31ed57548"
|
checksum = "98cc3af95fed6dc318dfede3e81320f96ad5e237c6f7c4688108b19c8e67432d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -738,18 +677,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_macros_support"
|
name = "pnet_macros_support"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4714e10f30cab023005adce048f2d30dd4ac4f093662abf2220855655ef8f90"
|
checksum = "feaba58ba96abb218ec584d6caf0d3ff48922df05dbbeb1560553c197091b29e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_packet"
|
name = "pnet_packet"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8588067671d03c9f4254b2e66fecb4d8b93b5d3e703195b84f311cd137e32130"
|
checksum = "f246edaaf1aaf82072d4cd38ee18bcc5dfc0464093f9ca39e4ac5962d68cf9d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -759,9 +698,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_sys"
|
name = "pnet_sys"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9a3f32b0df45515befd19eed04616f6b56a488da92afc61164ef455e955f07f"
|
checksum = "028c87a5e3a48fc07df099a2025f2ef16add5993712e1494ba69a6707ee7ed06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -769,9 +708,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnet_transport"
|
name = "pnet_transport"
|
||||||
version = "0.28.0"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "932b2916d693bcc5fa18443dc99142e0a6fd31a6ce75a511868f7174c17e2bce"
|
checksum = "950f2a7961e19d22e19e84ff0a6e0955013185fe149673499662633d02b41b7a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"pnet_base",
|
"pnet_base",
|
||||||
@@ -781,9 +720,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.30"
|
version = "1.0.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
@@ -801,9 +740,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.10"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -864,26 +803,20 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.2.3"
|
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 = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
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 = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
@@ -902,30 +835,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||||
dependencies = [
|
|
||||||
"semver-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver-parser"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.130"
|
version = "1.0.133"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.130"
|
version = "1.0.133"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -934,9 +858,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.68"
|
version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -945,9 +869,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.10"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
|
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -964,9 +888,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.7.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ssh2"
|
name = "ssh2"
|
||||||
@@ -988,15 +912,15 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.80"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1015,16 +939,6 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "term_size"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@@ -1034,6 +948,16 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "test_infra"
|
name = "test_infra"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1048,12 +972,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"term_size",
|
"terminal_size",
|
||||||
"unicode-width",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1076,12 +999,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -1103,12 +1020,6 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vec_map"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "versionize"
|
name = "versionize"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -1138,9 +1049,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a21f546f2bda37f5a8cfb138c87f95b8e34d2d78d6a7a92ba3785f4e08604a7"
|
checksum = "43449b404c488f70507dca193debd4bea361fe8089869b947adc19720e464bce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -1148,14 +1059,16 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#d51c1fad37be30c20385c55a217e2d90972ea31d"
|
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#19e5b83ddfad430109ce3e8d51f4a24796099127"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
"kvm-ioctls",
|
"kvm-ioctls",
|
||||||
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"mshv-bindings",
|
"mshv-bindings",
|
||||||
"mshv-ioctls",
|
"mshv-ioctls",
|
||||||
|
"thiserror",
|
||||||
"vfio-bindings",
|
"vfio-bindings",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -1193,9 +1106,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d23ddeb452fb4f837526c6298cc8a2f4948e5595b0328a3d61b5eebe51874d7"
|
checksum = "3b56bf8f178fc500fe14505fca8b00dec76fc38f2304f461c8d9d7547982311d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1212,6 +1125,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"vhost",
|
"vhost",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -1285,6 +1199,7 @@ dependencies = [
|
|||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -1293,6 +1208,16 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtio-queue"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"memoffset",
|
||||||
|
"vm-memory",
|
||||||
|
"vmm-sys-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-allocator"
|
name = "vm-allocator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1318,14 +1243,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-fdt"
|
name = "vm-fdt"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#9c2b252dc19f0e87546e4f7577eaf398f8e3c66a"
|
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#9cfa0c8d7c3032f79589c7b01c8722a37f4cf44f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
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 = "0a8ebcb86ca457f9d6e14cf97009f679952eba42f0113de5db596e514cd0e43b"
|
checksum = "339d4349c126fdcd87e034631d7274370cf19eb0e87b33166bcd956589fc72c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1352,6 +1277,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1366,7 +1292,6 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"block_util",
|
"block_util",
|
||||||
"clap",
|
"clap",
|
||||||
"credibility",
|
|
||||||
"devices",
|
"devices",
|
||||||
"epoll",
|
"epoll",
|
||||||
"event_monitor",
|
"event_monitor",
|
||||||
@@ -1393,6 +1318,7 @@ dependencies = [
|
|||||||
"vfio_user",
|
"vfio_user",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -1461,9 +1387,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae0f717764196a220d8c58500e3a3595e2c9054f95d66267f9fd5f6e74ad0fec"
|
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
@@ -1471,9 +1397,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0af017aca1fa6181f5dd7a802456fe6f7666ecdcc18d0910431f0fc89d474e51"
|
checksum = "a0fbc82b82efe24da867ee52e015e58178684bd9dd64c34e66bdf21da2582a9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"syn",
|
"syn",
|
||||||
|
|||||||
27
Cargo.toml
27
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "19.0.0"
|
version = "21.1.0"
|
||||||
authors = ["The Cloud Hypervisor Authors"]
|
authors = ["The Cloud Hypervisor Authors"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
default-run = "cloud-hypervisor"
|
default-run = "cloud-hypervisor"
|
||||||
@@ -13,55 +13,51 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
|||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.52"
|
||||||
api_client = { path = "api_client" }
|
api_client = { path = "api_client" }
|
||||||
clap = { version = "2.33.3", features = ["wrap_help"] }
|
clap = { version = "3.0.10", features = ["wrap_help","cargo"] }
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
event_monitor = { path = "event_monitor" }
|
event_monitor = { path = "event_monitor" }
|
||||||
hypervisor = { path = "hypervisor" }
|
hypervisor = { path = "hypervisor" }
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = { version = "0.4.14", features = ["std"] }
|
log = { version = "0.4.14", features = ["std"] }
|
||||||
option_parser = { path = "option_parser" }
|
option_parser = { path = "option_parser" }
|
||||||
seccompiler = "0.2.0"
|
seccompiler = "0.2.0"
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.75"
|
||||||
signal-hook = "0.3.10"
|
signal-hook = "0.3.13"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
vmm = { path = "vmm" }
|
vmm = { path = "vmm" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
vm-memory = "0.6.0"
|
vm-memory = "0.7.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "2.33.3", features = ["wrap_help"] }
|
clap = { version = "3.0.10", features = ["wrap_help"] }
|
||||||
|
|
||||||
# List of patched crates
|
# List of patched crates
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", features = ["with-serde", "fam-wrappers"] }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", features = ["with-serde", "fam-wrappers"] }
|
||||||
|
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" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
credibility = "0.1.3"
|
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
lazy_static= "1.4.0"
|
lazy_static= "1.4.0"
|
||||||
net_util = { path = "net_util" }
|
net_util = { path = "net_util" }
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.75"
|
||||||
test_infra = { path = "test_infra" }
|
test_infra = { path = "test_infra" }
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["common", "kvm"]
|
default = ["common", "kvm"]
|
||||||
# Common features for all hypervisors
|
# Common features for all hypervisors
|
||||||
common = ["acpi", "cmos", "fwdebug", "io_uring"]
|
common = ["acpi", "cmos", "fwdebug"]
|
||||||
acpi = ["vmm/acpi"]
|
acpi = ["vmm/acpi"]
|
||||||
cmos = ["vmm/cmos"]
|
cmos = ["vmm/cmos"]
|
||||||
fwdebug = ["vmm/fwdebug"]
|
fwdebug = ["vmm/fwdebug"]
|
||||||
kvm = ["vmm/kvm"]
|
kvm = ["vmm/kvm"]
|
||||||
mshv = ["vmm/mshv"]
|
mshv = ["vmm/mshv"]
|
||||||
io_uring = ["vmm/io_uring"]
|
|
||||||
tdx = ["vmm/tdx"]
|
tdx = ["vmm/tdx"]
|
||||||
|
|
||||||
# Integration tests require a special environment to run in
|
|
||||||
integration_tests = []
|
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"acpi_tables",
|
"acpi_tables",
|
||||||
@@ -83,6 +79,7 @@ members = [
|
|||||||
"vhost_user_block",
|
"vhost_user_block",
|
||||||
"vhost_user_net",
|
"vhost_user_net",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
|
"virtio-queue",
|
||||||
"vmm",
|
"vmm",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
|
|||||||
25
Jenkinsfile
vendored
25
Jenkinsfile
vendored
@@ -22,15 +22,19 @@ pipeline{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage ('Build') {
|
stage ('Build') {
|
||||||
parallel {
|
parallel {
|
||||||
stage ('Worker build') {
|
stage ('Worker build') {
|
||||||
agent { node { label 'hirsute' } }
|
agent { node { label 'hirsute' } }
|
||||||
|
environment {
|
||||||
|
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
|
||||||
|
}
|
||||||
stages {
|
stages {
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
steps {
|
steps {
|
||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Run OpenAPI tests') {
|
stage ('Run OpenAPI tests') {
|
||||||
steps {
|
steps {
|
||||||
sh "scripts/run_openapi_tests.sh"
|
sh "scripts/run_openapi_tests.sh"
|
||||||
@@ -84,12 +88,16 @@ pipeline{
|
|||||||
}
|
}
|
||||||
stage ('Worker build (musl)') {
|
stage ('Worker build (musl)') {
|
||||||
agent { node { label 'hirsute' } }
|
agent { node { label 'hirsute' } }
|
||||||
|
environment {
|
||||||
|
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
|
||||||
|
}
|
||||||
stages {
|
stages {
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
steps {
|
steps {
|
||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Run unit tests for musl') {
|
stage ('Run unit tests for musl') {
|
||||||
steps {
|
steps {
|
||||||
sh "scripts/dev_cli.sh tests --unit --libc musl"
|
sh "scripts/dev_cli.sh tests --unit --libc musl"
|
||||||
@@ -189,11 +197,14 @@ pipeline{
|
|||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage ('Install azure-cli') {
|
||||||
|
steps {
|
||||||
|
installAzureCli()
|
||||||
|
}
|
||||||
|
}
|
||||||
stage ('Download assets') {
|
stage ('Download assets') {
|
||||||
steps {
|
steps {
|
||||||
sh "sudo apt install -y azure-cli"
|
|
||||||
sh "mkdir ${env.HOME}/workloads"
|
sh "mkdir ${env.HOME}/workloads"
|
||||||
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/OVMF-4b47d0c6c8.fd" --name OVMF-4b47d0c6c8.fd --connection-string "$AZURE_CONNECTION_STRING"'
|
|
||||||
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2019.raw" --name windows-server-2019.raw --connection-string "$AZURE_CONNECTION_STRING"'
|
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2019.raw" --name windows-server-2019.raw --connection-string "$AZURE_CONNECTION_STRING"'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,3 +289,11 @@ def cancelPreviousBuilds() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def installAzureCli() {
|
||||||
|
sh "sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg"
|
||||||
|
sh "curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null"
|
||||||
|
sh "echo \"deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ hirsute main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
|
||||||
|
sh "sudo apt update"
|
||||||
|
sh "sudo apt install -y azure-cli"
|
||||||
|
}
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -4,6 +4,7 @@
|
|||||||
- [Architectures](#architectures)
|
- [Architectures](#architectures)
|
||||||
- [Guest OS](#guest-os)
|
- [Guest OS](#guest-os)
|
||||||
- [2. Getting Started](#2-getting-started)
|
- [2. Getting Started](#2-getting-started)
|
||||||
|
- [Preparation](#preparation)
|
||||||
- [Install prerequisites](#install-prerequisites)
|
- [Install prerequisites](#install-prerequisites)
|
||||||
- [Clone and build](#clone-and-build)
|
- [Clone and build](#clone-and-build)
|
||||||
- [Containerized builds and tests](#containerized-builds-and-tests)
|
- [Containerized builds and tests](#containerized-builds-and-tests)
|
||||||
@@ -58,6 +59,12 @@ Cloud Hypervisor supports `64-bit Linux` and Windows 10/Windows Server 2019.
|
|||||||
|
|
||||||
# 2. Getting Started
|
# 2. Getting Started
|
||||||
|
|
||||||
|
Below sections describe how to build and run Cloud Hypervisor on the `x86_64`
|
||||||
|
platform. For getting started on the `AArch64` platform, please refer to the
|
||||||
|
[Arm64 documentation](docs/arm64.md).
|
||||||
|
|
||||||
|
## Preparation
|
||||||
|
|
||||||
We create a folder to build and run `cloud-hypervisor` at `$HOME/cloud-hypervisor`
|
We create a folder to build and run `cloud-hypervisor` at `$HOME/cloud-hypervisor`
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -161,8 +168,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
|
|||||||
--disk path=focal-server-cloudimg-amd64.raw \
|
--disk path=focal-server-cloudimg-amd64.raw \
|
||||||
--cpus boot=4 \
|
--cpus boot=4 \
|
||||||
--memory size=1024M \
|
--memory size=1024M \
|
||||||
--net "tap=,mac=,ip=,mask=" \
|
--net "tap=,mac=,ip=,mask="
|
||||||
--rng
|
|
||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -180,12 +186,12 @@ To build the kernel:
|
|||||||
|
|
||||||
# Clone the Cloud Hypervisor Linux branch
|
# Clone the Cloud Hypervisor Linux branch
|
||||||
$ pushd $CLOUDH
|
$ pushd $CLOUDH
|
||||||
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-5.14 linux-cloud-hypervisor
|
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-5.15.12 linux-cloud-hypervisor
|
||||||
$ pushd linux-cloud-hypervisor
|
$ pushd linux-cloud-hypervisor
|
||||||
|
|
||||||
# Use the cloud-hypervisor kernel config to build your kernel
|
# Use the cloud-hypervisor kernel config to build your kernel
|
||||||
$ cp $CLOUDH/cloud-hypervisor/resources/linux-config-x86_64 .config
|
$ cp $CLOUDH/cloud-hypervisor/resources/linux-config-x86_64 .config
|
||||||
$ make bzImage -j `nproc`
|
$ KCFLAGS="-Wa,-mx86-used-note=no" make bzImage -j `nproc`
|
||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -216,8 +222,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
|
|||||||
--cmdline "console=hvc0 root=/dev/vda1 rw" \
|
--cmdline "console=hvc0 root=/dev/vda1 rw" \
|
||||||
--cpus boot=4 \
|
--cpus boot=4 \
|
||||||
--memory size=1024M \
|
--memory size=1024M \
|
||||||
--net "tap=,mac=,ip=,mask=" \
|
--net "tap=,mac=,ip=,mask="
|
||||||
--rng
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The above example use the `virtio-console` device as the guest console, and this
|
The above example use the `virtio-console` device as the guest console, and this
|
||||||
@@ -236,8 +241,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
|
|||||||
--cmdline "console=ttyS0 root=/dev/vda1 rw" \
|
--cmdline "console=ttyS0 root=/dev/vda1 rw" \
|
||||||
--cpus boot=4 \
|
--cpus boot=4 \
|
||||||
--memory size=1024M \
|
--memory size=1024M \
|
||||||
--net "tap=,mac=,ip=,mask=" \
|
--net "tap=,mac=,ip=,mask="
|
||||||
--rng
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# 3. Status
|
# 3. Status
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ authors = ["The Cloud Hypervisor Authors"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vm-memory = "0.6.0"
|
vm-memory = "0.7.0"
|
||||||
|
|||||||
@@ -6,15 +6,23 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait Aml {
|
pub trait Aml {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8>;
|
fn append_aml_bytes(&self, _v: &mut Vec<u8>) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_aml_bytes(&self) -> Vec<u8> {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
self.append_aml_bytes(&mut v);
|
||||||
|
v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ZERO: Zero = Zero {};
|
pub const ZERO: Zero = Zero {};
|
||||||
pub struct Zero {}
|
pub struct Zero {}
|
||||||
|
|
||||||
impl Aml for Zero {
|
impl Aml for Zero {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, v: &mut Vec<u8>) {
|
||||||
vec![0u8]
|
v.push(0u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,8 +30,8 @@ pub const ONE: One = One {};
|
|||||||
pub struct One {}
|
pub struct One {}
|
||||||
|
|
||||||
impl Aml for One {
|
impl Aml for One {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, v: &mut Vec<u8>) {
|
||||||
vec![1u8]
|
v.push(1u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +39,8 @@ pub const ONES: Ones = Ones {};
|
|||||||
pub struct Ones {}
|
pub struct Ones {}
|
||||||
|
|
||||||
impl Aml for Ones {
|
impl Aml for Ones {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, v: &mut Vec<u8>) {
|
||||||
vec![0xffu8]
|
v.push(0xffu8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,9 +50,7 @@ pub struct Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Path {
|
impl Aml for Path {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
|
|
||||||
if self.root {
|
if self.root {
|
||||||
bytes.push(b'\\');
|
bytes.push(b'\\');
|
||||||
}
|
}
|
||||||
@@ -62,10 +68,8 @@ impl Aml for Path {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for part in self.name_parts.clone().iter_mut() {
|
for part in self.name_parts.clone().iter_mut() {
|
||||||
bytes.append(&mut part.to_vec());
|
bytes.extend_from_slice(&part.to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,40 +98,36 @@ impl From<&str> for Path {
|
|||||||
pub type Byte = u8;
|
pub type Byte = u8;
|
||||||
|
|
||||||
impl Aml for Byte {
|
impl Aml for Byte {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x0a]; /* BytePrefix */
|
bytes.push(0x0a); /* BytePrefix */
|
||||||
bytes.push(*self);
|
bytes.push(*self);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Word = u16;
|
pub type Word = u16;
|
||||||
|
|
||||||
impl Aml for Word {
|
impl Aml for Word {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x0bu8]; /* WordPrefix */
|
bytes.push(0x0b); /* WordPrefix */
|
||||||
bytes.append(&mut self.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.to_le_bytes())
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DWord = u32;
|
pub type DWord = u32;
|
||||||
|
|
||||||
impl Aml for DWord {
|
impl Aml for DWord {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x0c]; /* DWordPrefix */
|
bytes.push(0x0c); /* DWordPrefix */
|
||||||
bytes.append(&mut self.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.to_le_bytes())
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type QWord = u64;
|
pub type QWord = u64;
|
||||||
|
|
||||||
impl Aml for QWord {
|
impl Aml for QWord {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x0e]; /* QWordPrefix */
|
bytes.push(0x0e); /* QWordPrefix */
|
||||||
bytes.append(&mut self.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.to_le_bytes())
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,16 +136,18 @@ pub struct Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Name {
|
impl Aml for Name {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
self.bytes.clone()
|
// TODO: Refactor this to make more efficient but there are
|
||||||
|
// lifetime/ownership challenges.
|
||||||
|
bytes.extend_from_slice(&self.bytes.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Name {
|
impl Name {
|
||||||
pub fn new(path: Path, inner: &dyn Aml) -> Self {
|
pub fn new(path: Path, inner: &dyn Aml) -> Self {
|
||||||
let mut bytes = vec![0x08]; /* NameOp */
|
let mut bytes = vec![0x08]; /* NameOp */
|
||||||
bytes.append(&mut path.to_aml_bytes());
|
path.append_aml_bytes(&mut bytes);
|
||||||
bytes.append(&mut inner.to_aml_bytes());
|
inner.append_aml_bytes(&mut bytes);
|
||||||
Name { bytes }
|
Name { bytes }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,21 +157,17 @@ pub struct Package<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Package<'a> {
|
impl<'a> Aml for Package<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![self.children.len() as u8];
|
let mut tmp = vec![self.children.len() as u8];
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
bytes.append(&mut child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x12); /* PackageOp */
|
bytes.push(0x12); /* PackageOp */
|
||||||
|
bytes.extend_from_slice(&pkg_length);
|
||||||
bytes
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,51 +255,46 @@ impl EisaName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for EisaName {
|
impl Aml for EisaName {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
self.value.to_aml_bytes()
|
self.value.append_aml_bytes(bytes)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_integer(v: usize) -> Vec<u8> {
|
|
||||||
if v <= u8::max_value().into() {
|
|
||||||
(v as u8).to_aml_bytes()
|
|
||||||
} else if v <= u16::max_value().into() {
|
|
||||||
(v as u16).to_aml_bytes()
|
|
||||||
} else if v <= u32::max_value() as usize {
|
|
||||||
(v as u32).to_aml_bytes()
|
|
||||||
} else {
|
|
||||||
(v as u64).to_aml_bytes()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Usize = usize;
|
pub type Usize = usize;
|
||||||
|
|
||||||
impl Aml for Usize {
|
impl Aml for Usize {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
create_integer(*self)
|
if *self <= u8::max_value().into() {
|
||||||
|
(*self as u8).append_aml_bytes(bytes)
|
||||||
|
} else if *self <= u16::max_value().into() {
|
||||||
|
(*self as u16).append_aml_bytes(bytes)
|
||||||
|
} else if *self <= u32::max_value() as usize {
|
||||||
|
(*self as u32).append_aml_bytes(bytes)
|
||||||
|
} else {
|
||||||
|
(*self as u64).append_aml_bytes(bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_aml_string(v: &str) -> Vec<u8> {
|
fn append_aml_string(v: &str, bytes: &mut Vec<u8>) {
|
||||||
let mut data = vec![0x0D]; /* String Op */
|
bytes.push(0x0D); /* String Op */
|
||||||
data.extend_from_slice(v.as_bytes());
|
bytes.extend_from_slice(v.as_bytes());
|
||||||
data.push(0x0); /* NullChar */
|
bytes.push(0x0); /* NullChar */
|
||||||
data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type AmlStr = &'static str;
|
pub type AmlStr = &'static str;
|
||||||
|
|
||||||
impl Aml for AmlStr {
|
impl Aml for AmlStr {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
create_aml_string(self)
|
append_aml_string(self, bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type AmlString = String;
|
pub type AmlString = String;
|
||||||
|
|
||||||
impl Aml for AmlString {
|
impl Aml for AmlString {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
create_aml_string(self)
|
append_aml_string(self, bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,36 +303,31 @@ pub struct ResourceTemplate<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for ResourceTemplate<'a> {
|
impl<'a> Aml for ResourceTemplate<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
|
|
||||||
// Add buffer data
|
// Add buffer data
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
bytes.append(&mut child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark with end and mark checksum as as always valid
|
// Mark with end and mark checksum as as always valid
|
||||||
bytes.push(0x79); /* EndTag */
|
tmp.push(0x79); /* EndTag */
|
||||||
bytes.push(0); /* zero checksum byte */
|
tmp.push(0); /* zero checksum byte */
|
||||||
|
|
||||||
// Buffer length is an encoded integer including buffer data
|
// Buffer length is an encoded integer including buffer data
|
||||||
// and EndTag and checksum byte
|
// and EndTag and checksum byte
|
||||||
let mut buffer_length = bytes.len().to_aml_bytes();
|
let mut buffer_length = tmp.len().to_aml_bytes();
|
||||||
buffer_length.reverse();
|
buffer_length.reverse();
|
||||||
for byte in buffer_length {
|
for byte in buffer_length {
|
||||||
bytes.insert(0, byte);
|
tmp.insert(0, byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PkgLength is everything else
|
// PkgLength is everything else
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x11); /* BufferOp */
|
bytes.push(0x11); /* BufferOp */
|
||||||
|
bytes.extend_from_slice(&pkg_length);
|
||||||
bytes
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,15 +354,13 @@ impl Memory32Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Memory32Fixed {
|
impl Aml for Memory32Fixed {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x86]; /* Memory32Fixed */
|
bytes.push(0x86); /* Memory32Fixed */
|
||||||
bytes.append(&mut 9u16.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&9u16.to_le_bytes());
|
||||||
|
|
||||||
// 9 bytes of payload
|
// 9 bytes of payload
|
||||||
bytes.push(self.read_write as u8);
|
bytes.push(self.read_write as u8);
|
||||||
bytes.append(&mut self.base.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.base.to_le_bytes());
|
||||||
bytes.append(&mut self.length.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.length.to_le_bytes());
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +416,7 @@ impl<T> AddressSpace<T> {
|
|||||||
|
|
||||||
fn push_header(&self, bytes: &mut Vec<u8>, descriptor: u8, length: usize) {
|
fn push_header(&self, bytes: &mut Vec<u8>, descriptor: u8, length: usize) {
|
||||||
bytes.push(descriptor); /* Word Address Space Descriptor */
|
bytes.push(descriptor); /* Word Address Space Descriptor */
|
||||||
bytes.append(&mut (length as u16).to_le_bytes().to_vec());
|
bytes.extend_from_slice(&(length as u16).to_le_bytes());
|
||||||
bytes.push(self.r#type as u8); /* type */
|
bytes.push(self.r#type as u8); /* type */
|
||||||
let generic_flags = 1 << 2 /* Min Fixed */ | 1 << 3; /* Max Fixed */
|
let generic_flags = 1 << 2 /* Min Fixed */ | 1 << 3; /* Max Fixed */
|
||||||
bytes.push(generic_flags);
|
bytes.push(generic_flags);
|
||||||
@@ -439,65 +425,53 @@ impl<T> AddressSpace<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for AddressSpace<u16> {
|
impl Aml for AddressSpace<u16> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
|
|
||||||
self.push_header(
|
self.push_header(
|
||||||
&mut bytes,
|
bytes,
|
||||||
0x88, /* Word Address Space Descriptor */
|
0x88, /* Word Address Space Descriptor */
|
||||||
3 + 5 * std::mem::size_of::<u16>(), /* 3 bytes of header + 5 u16 fields */
|
3 + 5 * std::mem::size_of::<u16>(), /* 3 bytes of header + 5 u16 fields */
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes.append(&mut 0u16.to_le_bytes().to_vec()); /* Granularity */
|
bytes.extend_from_slice(&0u16.to_le_bytes()); /* Granularity */
|
||||||
bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
|
bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
|
||||||
bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
|
bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
|
||||||
bytes.append(&mut 0u16.to_le_bytes().to_vec()); /* Translation */
|
bytes.extend_from_slice(&0u16.to_le_bytes()); /* Translation */
|
||||||
let len = self.max - self.min + 1;
|
let len = self.max - self.min + 1;
|
||||||
bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
|
bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for AddressSpace<u32> {
|
impl Aml for AddressSpace<u32> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
|
|
||||||
self.push_header(
|
self.push_header(
|
||||||
&mut bytes,
|
bytes,
|
||||||
0x87, /* DWord Address Space Descriptor */
|
0x87, /* DWord Address Space Descriptor */
|
||||||
3 + 5 * std::mem::size_of::<u32>(), /* 3 bytes of header + 5 u32 fields */
|
3 + 5 * std::mem::size_of::<u32>(), /* 3 bytes of header + 5 u32 fields */
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes.append(&mut 0u32.to_le_bytes().to_vec()); /* Granularity */
|
bytes.extend_from_slice(&0u32.to_le_bytes()); /* Granularity */
|
||||||
bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
|
bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
|
||||||
bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
|
bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
|
||||||
bytes.append(&mut 0u32.to_le_bytes().to_vec()); /* Translation */
|
bytes.extend_from_slice(&0u32.to_le_bytes()); /* Translation */
|
||||||
let len = self.max - self.min + 1;
|
let len = self.max - self.min + 1;
|
||||||
bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
|
bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for AddressSpace<u64> {
|
impl Aml for AddressSpace<u64> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
|
|
||||||
self.push_header(
|
self.push_header(
|
||||||
&mut bytes,
|
bytes,
|
||||||
0x8A, /* QWord Address Space Descriptor */
|
0x8A, /* QWord Address Space Descriptor */
|
||||||
3 + 5 * std::mem::size_of::<u64>(), /* 3 bytes of header + 5 u64 fields */
|
3 + 5 * std::mem::size_of::<u64>(), /* 3 bytes of header + 5 u64 fields */
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes.append(&mut 0u64.to_le_bytes().to_vec()); /* Granularity */
|
bytes.extend_from_slice(&0u64.to_le_bytes()); /* Granularity */
|
||||||
bytes.append(&mut self.min.to_le_bytes().to_vec()); /* Min */
|
bytes.extend_from_slice(&self.min.to_le_bytes()); /* Min */
|
||||||
bytes.append(&mut self.max.to_le_bytes().to_vec()); /* Max */
|
bytes.extend_from_slice(&self.max.to_le_bytes()); /* Max */
|
||||||
bytes.append(&mut 0u64.to_le_bytes().to_vec()); /* Translation */
|
bytes.extend_from_slice(&0u64.to_le_bytes()); /* Translation */
|
||||||
let len = self.max - self.min + 1;
|
let len = self.max - self.min + 1;
|
||||||
bytes.append(&mut len.to_le_bytes().to_vec()); /* Length */
|
bytes.extend_from_slice(&len.to_le_bytes()); /* Length */
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,16 +494,13 @@ impl Io {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Io {
|
impl Aml for Io {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x47]; /* Io Port Descriptor */
|
bytes.push(0x47); /* Io Port Descriptor */
|
||||||
|
|
||||||
bytes.push(1); /* IODecode16 */
|
bytes.push(1); /* IODecode16 */
|
||||||
bytes.append(&mut self.min.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.min.to_le_bytes());
|
||||||
bytes.append(&mut self.max.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.max.to_le_bytes());
|
||||||
bytes.push(self.alignment);
|
bytes.push(self.alignment);
|
||||||
bytes.push(self.length);
|
bytes.push(self.length);
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,18 +531,16 @@ impl Interrupt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Interrupt {
|
impl Aml for Interrupt {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x89]; /* Extended IRQ Descriptor */
|
bytes.push(0x89); /* Extended IRQ Descriptor */
|
||||||
bytes.append(&mut 6u16.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&6u16.to_le_bytes());
|
||||||
let flags = (self.shared as u8) << 3
|
let flags = (self.shared as u8) << 3
|
||||||
| (self.active_low as u8) << 2
|
| (self.active_low as u8) << 2
|
||||||
| (self.edge_triggered as u8) << 1
|
| (self.edge_triggered as u8) << 1
|
||||||
| self.consumer as u8;
|
| self.consumer as u8;
|
||||||
bytes.push(flags);
|
bytes.push(flags);
|
||||||
bytes.push(1u8); /* count */
|
bytes.push(1u8); /* count */
|
||||||
bytes.append(&mut self.number.to_le_bytes().to_vec());
|
bytes.extend_from_slice(&self.number.to_le_bytes());
|
||||||
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,22 +550,20 @@ pub struct Device<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Device<'a> {
|
impl<'a> Aml for Device<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.append(&mut self.path.to_aml_bytes());
|
self.path.append_aml_bytes(&mut tmp);
|
||||||
|
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
bytes.append(&mut child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x82); /* DeviceOp */
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.insert(0, 0x5b); /* ExtOpPrefix */
|
bytes.push(0x82); /* DeviceOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,21 +579,18 @@ pub struct Scope<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Scope<'a> {
|
impl<'a> Aml for Scope<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.append(&mut self.path.to_aml_bytes());
|
self.path.append_aml_bytes(&mut tmp);
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
bytes.append(&mut child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x10); /* ScopeOp */
|
bytes.push(0x10); /* ScopeOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,23 +619,20 @@ impl<'a> Method<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Method<'a> {
|
impl<'a> Aml for Method<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.append(&mut self.path.to_aml_bytes());
|
self.path.append_aml_bytes(&mut tmp);
|
||||||
let flags: u8 = (self.args & 0x7) | (self.serialized as u8) << 3;
|
let flags: u8 = (self.args & 0x7) | (self.serialized as u8) << 3;
|
||||||
bytes.push(flags);
|
tmp.push(flags);
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
bytes.append(&mut child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x14); /* MethodOp */
|
bytes.push(0x14); /* MethodOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,10 +647,9 @@ impl<'a> Return<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Return<'a> {
|
impl<'a> Aml for Return<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0xa4]; /* ReturnOp */
|
bytes.push(0xa4); /* ReturnOp */
|
||||||
bytes.append(&mut self.value.to_aml_bytes());
|
self.value.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,35 +700,32 @@ impl Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Field {
|
impl Aml for Field {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.append(&mut self.path.to_aml_bytes());
|
self.path.append_aml_bytes(&mut tmp);
|
||||||
|
|
||||||
let flags: u8 = self.access_type as u8 | (self.update_rule as u8) << 5;
|
let flags: u8 = self.access_type as u8 | (self.update_rule as u8) << 5;
|
||||||
bytes.push(flags);
|
tmp.push(flags);
|
||||||
|
|
||||||
for field in self.fields.iter() {
|
for field in self.fields.iter() {
|
||||||
match field {
|
match field {
|
||||||
FieldEntry::Named(name, length) => {
|
FieldEntry::Named(name, length) => {
|
||||||
bytes.extend_from_slice(name);
|
tmp.extend_from_slice(name);
|
||||||
bytes.append(&mut create_pkg_length(&vec![0; *length], false));
|
tmp.extend_from_slice(&create_pkg_length(&vec![0; *length], false));
|
||||||
}
|
}
|
||||||
FieldEntry::Reserved(length) => {
|
FieldEntry::Reserved(length) => {
|
||||||
bytes.push(0x0);
|
tmp.push(0x0);
|
||||||
bytes.append(&mut create_pkg_length(&vec![0; *length], false));
|
tmp.extend_from_slice(&create_pkg_length(&vec![0; *length], false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x81); /* FieldOp */
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.insert(0, 0x5b); /* ExtOpPrefix */
|
bytes.push(0x81); /* FieldOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,15 +762,13 @@ impl OpRegion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for OpRegion {
|
impl Aml for OpRegion {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.append(&mut self.path.to_aml_bytes());
|
bytes.push(0x80); /* OpRegionOp */
|
||||||
|
self.path.append_aml_bytes(bytes);
|
||||||
bytes.push(self.space as u8);
|
bytes.push(self.space as u8);
|
||||||
bytes.extend_from_slice(&self.offset.to_aml_bytes()); /* RegionOffset */
|
self.offset.append_aml_bytes(bytes); /* RegionOffset */
|
||||||
bytes.extend_from_slice(&self.length.to_aml_bytes()); /* RegionLen */
|
self.length.append_aml_bytes(bytes); /* RegionLen */
|
||||||
bytes.insert(0, 0x80); /* OpRegionOp */
|
|
||||||
bytes.insert(0, 0x5b); /* ExtOpPrefix */
|
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,21 +787,18 @@ impl<'a> If<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for If<'a> {
|
impl<'a> Aml for If<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.extend_from_slice(&self.predicate.to_aml_bytes());
|
self.predicate.append_aml_bytes(&mut tmp);
|
||||||
for child in self.if_children.iter() {
|
for child in self.if_children.iter() {
|
||||||
bytes.extend_from_slice(&child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0xa0); /* IfOp */
|
bytes.push(0xa0); /* IfOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,11 +814,10 @@ impl<'a> Equal<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Equal<'a> {
|
impl<'a> Aml for Equal<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x93]; /* LEqualOp */
|
bytes.push(0x93); /* LEqualOp */
|
||||||
bytes.extend_from_slice(&self.left.to_aml_bytes());
|
self.left.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.right.to_aml_bytes());
|
self.right.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,33 +833,28 @@ impl<'a> LessThan<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for LessThan<'a> {
|
impl<'a> Aml for LessThan<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x95]; /* LLessOp */
|
bytes.push(0x95); /* LLessOp */
|
||||||
bytes.extend_from_slice(&self.left.to_aml_bytes());
|
self.left.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.right.to_aml_bytes());
|
self.right.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Arg(pub u8);
|
pub struct Arg(pub u8);
|
||||||
|
|
||||||
impl Aml for Arg {
|
impl Aml for Arg {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
assert!(self.0 <= 6);
|
assert!(self.0 <= 6);
|
||||||
bytes.push(0x68 + self.0); /* Arg0Op */
|
bytes.push(0x68 + self.0); /* Arg0Op */
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Local(pub u8);
|
pub struct Local(pub u8);
|
||||||
|
|
||||||
impl Aml for Local {
|
impl Aml for Local {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
|
||||||
assert!(self.0 <= 7);
|
assert!(self.0 <= 7);
|
||||||
bytes.push(0x60 + self.0); /* Local0Op */
|
bytes.push(0x60 + self.0); /* Local0Op */
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,11 +870,10 @@ impl<'a> Store<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Store<'a> {
|
impl<'a> Aml for Store<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x70]; /* StoreOp */
|
bytes.push(0x70); /* StoreOp */
|
||||||
bytes.extend_from_slice(&self.value.to_aml_bytes());
|
self.value.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.name.to_aml_bytes());
|
self.name.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,12 +889,11 @@ impl Mutex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Mutex {
|
impl Aml for Mutex {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.push(0x01); /* MutexOp */
|
bytes.push(0x01); /* MutexOp */
|
||||||
bytes.extend_from_slice(&self.path.to_aml_bytes());
|
self.path.append_aml_bytes(bytes);
|
||||||
bytes.push(self.sync_level);
|
bytes.push(self.sync_level);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,12 +909,11 @@ impl Acquire {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Acquire {
|
impl Aml for Acquire {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.push(0x23); /* AcquireOp */
|
bytes.push(0x23); /* AcquireOp */
|
||||||
bytes.extend_from_slice(&self.mutex.to_aml_bytes());
|
self.mutex.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.timeout.to_le_bytes());
|
bytes.extend_from_slice(&self.timeout.to_le_bytes());
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -985,11 +928,10 @@ impl Release {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Release {
|
impl Aml for Release {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x5b]; /* ExtOpPrefix */
|
bytes.push(0x5b); /* ExtOpPrefix */
|
||||||
bytes.push(0x27); /* ReleaseOp */
|
bytes.push(0x27); /* ReleaseOp */
|
||||||
bytes.extend_from_slice(&self.mutex.to_aml_bytes());
|
self.mutex.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1005,11 +947,10 @@ impl<'a> Notify<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for Notify<'a> {
|
impl<'a> Aml for Notify<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x86]; /* NotifyOp */
|
bytes.push(0x86); /* NotifyOp */
|
||||||
bytes.extend_from_slice(&self.object.to_aml_bytes());
|
self.object.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.value.to_aml_bytes());
|
self.value.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,21 +969,18 @@ impl<'a> While<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for While<'a> {
|
impl<'a> Aml for While<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.extend_from_slice(&self.predicate.to_aml_bytes());
|
self.predicate.append_aml_bytes(&mut tmp);
|
||||||
for child in self.while_children.iter() {
|
for child in self.while_children.iter() {
|
||||||
bytes.extend_from_slice(&child.to_aml_bytes());
|
child.append_aml_bytes(&mut tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0xa2); /* WhileOp */
|
bytes.push(0xa2); /* WhileOp */
|
||||||
bytes
|
bytes.extend_from_slice(&pkg_length);
|
||||||
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,12 +999,11 @@ macro_rules! binary_op {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for $name<'a> {
|
impl<'a> Aml for $name<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![$opcode]; /* Op for the binary operator */
|
bytes.push($opcode); /* Op for the binary operator */
|
||||||
bytes.extend_from_slice(&self.a.to_aml_bytes());
|
self.a.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.b.to_aml_bytes());
|
self.b.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.target.to_aml_bytes());
|
self.target.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1101,13 +1038,11 @@ impl<'a> MethodCall<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for MethodCall<'a> {
|
impl<'a> Aml for MethodCall<'a> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
self.name.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.name.to_aml_bytes());
|
|
||||||
for arg in self.args.iter() {
|
for arg in self.args.iter() {
|
||||||
bytes.extend_from_slice(&arg.to_aml_bytes());
|
arg.append_aml_bytes(bytes);
|
||||||
}
|
}
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1122,20 +1057,16 @@ impl Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Aml for Buffer {
|
impl Aml for Buffer {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = Vec::new();
|
let mut tmp = Vec::new();
|
||||||
bytes.extend_from_slice(&self.data.len().to_aml_bytes());
|
self.data.len().append_aml_bytes(&mut tmp);
|
||||||
bytes.extend_from_slice(&self.data);
|
tmp.extend_from_slice(&self.data);
|
||||||
|
|
||||||
let mut pkg_length = create_pkg_length(&bytes, true);
|
let pkg_length = create_pkg_length(&tmp, true);
|
||||||
pkg_length.reverse();
|
|
||||||
for byte in pkg_length {
|
|
||||||
bytes.insert(0, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.insert(0, 0x11); /* BufferOp */
|
bytes.push(0x11); /* BufferOp */
|
||||||
|
bytes.extend_from_slice(&pkg_length);
|
||||||
bytes
|
bytes.extend_from_slice(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,22 +1089,20 @@ impl<'a, T> CreateField<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for CreateField<'a, u64> {
|
impl<'a> Aml for CreateField<'a, u64> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x8f]; /* CreateQWordFieldOp */
|
bytes.push(0x8f); /* CreateQWordFieldOp */
|
||||||
bytes.extend_from_slice(&self.buffer.to_aml_bytes());
|
self.buffer.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.offset.to_aml_bytes());
|
self.offset.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.field.to_aml_bytes());
|
self.field.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Aml for CreateField<'a, u32> {
|
impl<'a> Aml for CreateField<'a, u32> {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
let mut bytes = vec![0x8a]; /* CreateDWordFieldOp */
|
bytes.push(0x8a); /* CreateDWordFieldOp */
|
||||||
bytes.extend_from_slice(&self.buffer.to_aml_bytes());
|
self.buffer.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.offset.to_aml_bytes());
|
self.offset.append_aml_bytes(bytes);
|
||||||
bytes.extend_from_slice(&self.field.to_aml_bytes());
|
self.field.append_aml_bytes(bytes);
|
||||||
bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1463,13 +1392,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pkg_length() {
|
fn test_pkg_length() {
|
||||||
assert_eq!(create_pkg_length(&[0u8; 62].to_vec(), true), vec![63]);
|
assert_eq!(create_pkg_length(&[0u8; 62], true), vec![63]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
create_pkg_length(&[0u8; 64].to_vec(), true),
|
create_pkg_length(&[0u8; 64], true),
|
||||||
vec![1 << 6 | (66 & 0xf), 66 >> 4]
|
vec![1 << 6 | (66 & 0xf), 66 >> 4]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
create_pkg_length(&[0u8; 4096].to_vec(), true),
|
create_pkg_length(&[0u8; 4096], true),
|
||||||
vec![
|
vec![
|
||||||
2 << 6 | (4099 & 0xf) as u8,
|
2 << 6 | (4099 & 0xf) as u8,
|
||||||
(4099 >> 4) as u8,
|
(4099 >> 4) as u8,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub struct Rsdp {
|
|||||||
_reserved: [u8; 3],
|
_reserved: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: Rsdp only contains a series of integers
|
||||||
unsafe impl ByteValued for Rsdp {}
|
unsafe impl ByteValued for Rsdp {}
|
||||||
|
|
||||||
impl Rsdp {
|
impl Rsdp {
|
||||||
|
|||||||
@@ -11,18 +11,18 @@ tdx = []
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables", optional = true }
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.52"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
linux-loader = { version = "0.4.0", features = ["elf", "bzimage", "pe"] }
|
linux-loader = { version = "0.4.0", features = ["elf", "bzimage", "pe"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
serde = { version = "1.0.130", features = ["rc"] }
|
serde = { version = "1.0.133", features = ["rc"] }
|
||||||
serde_derive = "1.0.130"
|
serde_derive = "1.0.133"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-bitmap"] }
|
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use crate::NumaNodes;
|
use crate::{NumaNodes, PciSpaceInfo};
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -22,7 +22,7 @@ use super::get_fdt_addr;
|
|||||||
use super::gic::GicDevice;
|
use super::gic::GicDevice;
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
|
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
|
||||||
PCI_HIGH_BASE, PCI_MMCONFIG_SIZE, PCI_MMCONFIG_START,
|
PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
|
||||||
};
|
};
|
||||||
use vm_fdt::{FdtWriter, FdtWriterResult};
|
use vm_fdt::{FdtWriter, FdtWriterResult};
|
||||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryRegion};
|
||||||
@@ -88,7 +88,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
device_info: &HashMap<(DeviceType, String), T, S>,
|
device_info: &HashMap<(DeviceType, String), T, S>,
|
||||||
gic_device: &dyn GicDevice,
|
gic_device: &dyn GicDevice,
|
||||||
initrd: &Option<InitramfsConfig>,
|
initrd: &Option<InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_info: &[PciSpaceInfo],
|
||||||
numa_nodes: &NumaNodes,
|
numa_nodes: &NumaNodes,
|
||||||
virtio_iommu_bdf: Option<u32>,
|
virtio_iommu_bdf: Option<u32>,
|
||||||
) -> FdtWriterResult<Vec<u8>> {
|
) -> FdtWriterResult<Vec<u8>> {
|
||||||
@@ -117,12 +117,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
|
|||||||
create_clock_node(&mut fdt)?;
|
create_clock_node(&mut fdt)?;
|
||||||
create_psci_node(&mut fdt)?;
|
create_psci_node(&mut fdt)?;
|
||||||
create_devices_node(&mut fdt, device_info)?;
|
create_devices_node(&mut fdt, device_info)?;
|
||||||
create_pci_nodes(
|
create_pci_nodes(&mut fdt, pci_space_info, virtio_iommu_bdf)?;
|
||||||
&mut fdt,
|
|
||||||
pci_space_address.0,
|
|
||||||
pci_space_address.1,
|
|
||||||
virtio_iommu_bdf,
|
|
||||||
)?;
|
|
||||||
if numa_nodes.len() > 1 {
|
if numa_nodes.len() > 1 {
|
||||||
create_distance_map_node(&mut fdt, numa_nodes)?;
|
create_distance_map_node(&mut fdt, numa_nodes)?;
|
||||||
}
|
}
|
||||||
@@ -547,108 +542,145 @@ fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Buil
|
|||||||
|
|
||||||
fn create_pci_nodes(
|
fn create_pci_nodes(
|
||||||
fdt: &mut FdtWriter,
|
fdt: &mut FdtWriter,
|
||||||
pci_device_base: u64,
|
pci_device_info: &[PciSpaceInfo],
|
||||||
pci_device_size: u64,
|
|
||||||
virtio_iommu_bdf: Option<u32>,
|
virtio_iommu_bdf: Option<u32>,
|
||||||
) -> FdtWriterResult<()> {
|
) -> FdtWriterResult<()> {
|
||||||
// Add node for PCIe controller.
|
// Add node for PCIe controller.
|
||||||
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
|
||||||
// and https://elinux.org/Device_Tree_Usage.
|
// and https://elinux.org/Device_Tree_Usage.
|
||||||
|
// In multiple PCI segments setup, each PCI segment needs a PCI node.
|
||||||
|
for pci_device_info_elem in pci_device_info.iter() {
|
||||||
|
// EDK2 requires the PCIe high space above 4G address.
|
||||||
|
// The actual space in CLH follows the RAM. If the RAM space is small, the PCIe high space
|
||||||
|
// could fall bellow 4G.
|
||||||
|
// Here we cut off PCI device space below 8G in FDT to workaround the EDK2 check.
|
||||||
|
// But the address written in ACPI is not impacted.
|
||||||
|
let (pci_device_base_64bit, pci_device_size_64bit) = if cfg!(feature = "acpi")
|
||||||
|
&& (pci_device_info_elem.pci_device_space_start < PCI_HIGH_BASE)
|
||||||
|
{
|
||||||
|
(
|
||||||
|
PCI_HIGH_BASE,
|
||||||
|
pci_device_info_elem.pci_device_space_size
|
||||||
|
- (PCI_HIGH_BASE - pci_device_info_elem.pci_device_space_start),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
pci_device_info_elem.pci_device_space_start,
|
||||||
|
pci_device_info_elem.pci_device_space_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
// There is no specific requirement of the 32bit MMIO range, and
|
||||||
|
// therefore at least we can make these ranges 4K aligned.
|
||||||
|
let pci_device_size_32bit: u64 =
|
||||||
|
MEM_32BIT_DEVICES_SIZE / ((1 << 12) * pci_device_info.len() as u64) * (1 << 12);
|
||||||
|
let pci_device_base_32bit: u64 = MEM_32BIT_DEVICES_START.0
|
||||||
|
+ pci_device_size_32bit * pci_device_info_elem.pci_segment_id as u64;
|
||||||
|
|
||||||
// EDK2 requires the PCIe high space above 4G address.
|
let ranges = [
|
||||||
// The actual space in CLH follows the RAM. If the RAM space is small, the PCIe high space
|
// io addresses. Since AArch64 will not use IO address,
|
||||||
// could fall bellow 4G.
|
// we can set the same IO address range for every segment.
|
||||||
// Here we put it above 512G in FDT to workaround the EDK2 check.
|
0x1000000,
|
||||||
// But the address written in ACPI is not impacted.
|
|
||||||
let pci_device_base_64bit: u64 = if cfg!(feature = "acpi") {
|
|
||||||
pci_device_base + PCI_HIGH_BASE
|
|
||||||
} else {
|
|
||||||
pci_device_base
|
|
||||||
};
|
|
||||||
let pci_device_size_64bit: u64 = if cfg!(feature = "acpi") {
|
|
||||||
pci_device_size - PCI_HIGH_BASE
|
|
||||||
} else {
|
|
||||||
pci_device_size
|
|
||||||
};
|
|
||||||
|
|
||||||
let ranges = [
|
|
||||||
// io addresses
|
|
||||||
0x1000000,
|
|
||||||
0_u32,
|
|
||||||
0_u32,
|
|
||||||
(MEM_PCI_IO_START.0 >> 32) as u32,
|
|
||||||
MEM_PCI_IO_START.0 as u32,
|
|
||||||
(MEM_PCI_IO_SIZE >> 32) as u32,
|
|
||||||
MEM_PCI_IO_SIZE as u32,
|
|
||||||
// mmio addresses
|
|
||||||
0x2000000, // (ss = 10: 32-bit memory space)
|
|
||||||
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // PCI address
|
|
||||||
MEM_32BIT_DEVICES_START.0 as u32,
|
|
||||||
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // CPU address
|
|
||||||
MEM_32BIT_DEVICES_START.0 as u32,
|
|
||||||
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // size
|
|
||||||
MEM_32BIT_DEVICES_SIZE as u32,
|
|
||||||
// device addresses
|
|
||||||
0x3000000, // (ss = 11: 64-bit memory space)
|
|
||||||
(pci_device_base_64bit >> 32) as u32, // PCI address
|
|
||||||
pci_device_base_64bit as u32,
|
|
||||||
(pci_device_base_64bit >> 32) as u32, // CPU address
|
|
||||||
pci_device_base_64bit as u32,
|
|
||||||
(pci_device_size_64bit >> 32) as u32, // size
|
|
||||||
pci_device_size_64bit as u32,
|
|
||||||
];
|
|
||||||
let bus_range = [0, 0]; // Only bus 0
|
|
||||||
let reg = [PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE];
|
|
||||||
|
|
||||||
let pci_node = fdt.begin_node("pci")?;
|
|
||||||
fdt.property_string("compatible", "pci-host-ecam-generic")?;
|
|
||||||
fdt.property_string("device_type", "pci")?;
|
|
||||||
fdt.property_array_u32("ranges", &ranges)?;
|
|
||||||
fdt.property_array_u32("bus-range", &bus_range)?;
|
|
||||||
fdt.property_u32("#address-cells", 3)?;
|
|
||||||
fdt.property_u32("#size-cells", 2)?;
|
|
||||||
fdt.property_array_u64("reg", ®)?;
|
|
||||||
fdt.property_u32("#interrupt-cells", 1)?;
|
|
||||||
fdt.property_null("interrupt-map")?;
|
|
||||||
fdt.property_null("interrupt-map-mask")?;
|
|
||||||
fdt.property_null("dma-coherent")?;
|
|
||||||
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
|
|
||||||
|
|
||||||
if let Some(virtio_iommu_bdf) = virtio_iommu_bdf {
|
|
||||||
// See kernel document Documentation/devicetree/bindings/pci/pci-iommu.txt
|
|
||||||
// for 'iommu-map' attribute setting.
|
|
||||||
let iommu_map = [
|
|
||||||
0_u32,
|
0_u32,
|
||||||
VIRTIO_IOMMU_PHANDLE,
|
|
||||||
0_u32,
|
0_u32,
|
||||||
virtio_iommu_bdf,
|
(MEM_PCI_IO_START.0 >> 32) as u32,
|
||||||
virtio_iommu_bdf + 1,
|
MEM_PCI_IO_START.0 as u32,
|
||||||
VIRTIO_IOMMU_PHANDLE,
|
(MEM_PCI_IO_SIZE >> 32) as u32,
|
||||||
virtio_iommu_bdf + 1,
|
MEM_PCI_IO_SIZE as u32,
|
||||||
0xffff - virtio_iommu_bdf,
|
// mmio addresses
|
||||||
|
0x2000000, // (ss = 10: 32-bit memory space)
|
||||||
|
(pci_device_base_32bit >> 32) as u32, // PCI address
|
||||||
|
pci_device_base_32bit as u32,
|
||||||
|
(pci_device_base_32bit >> 32) as u32, // CPU address
|
||||||
|
pci_device_base_32bit as u32,
|
||||||
|
(pci_device_size_32bit >> 32) as u32, // size
|
||||||
|
pci_device_size_32bit as u32,
|
||||||
|
// device addresses
|
||||||
|
0x3000000, // (ss = 11: 64-bit memory space)
|
||||||
|
(pci_device_base_64bit >> 32) as u32, // PCI address
|
||||||
|
pci_device_base_64bit as u32,
|
||||||
|
(pci_device_base_64bit >> 32) as u32, // CPU address
|
||||||
|
pci_device_base_64bit as u32,
|
||||||
|
(pci_device_size_64bit >> 32) as u32, // size
|
||||||
|
pci_device_size_64bit as u32,
|
||||||
|
];
|
||||||
|
let bus_range = [0, 0]; // Only bus 0
|
||||||
|
let reg = [
|
||||||
|
pci_device_info_elem.mmio_config_address,
|
||||||
|
PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
|
||||||
|
];
|
||||||
|
// See kernel document Documentation/devicetree/bindings/pci/pci-msi.txt
|
||||||
|
let msi_map = [
|
||||||
|
// rid-base: A single cell describing the first RID matched by the entry.
|
||||||
|
0x0,
|
||||||
|
// msi-controller: A single phandle to an MSI controller.
|
||||||
|
MSI_PHANDLE,
|
||||||
|
// msi-base: An msi-specifier describing the msi-specifier produced for the
|
||||||
|
// first RID matched by the entry.
|
||||||
|
(pci_device_info_elem.pci_segment_id as u32) << 8,
|
||||||
|
// length: A single cell describing how many consecutive RIDs are matched
|
||||||
|
// following the rid-base.
|
||||||
|
0x100,
|
||||||
];
|
];
|
||||||
fdt.property_array_u32("iommu-map", &iommu_map)?;
|
|
||||||
|
|
||||||
// See kernel document Documentation/devicetree/bindings/virtio/iommu.txt
|
let pci_node_name = format!("pci@{:x}", pci_device_info_elem.mmio_config_address);
|
||||||
// for virtio-iommu node settings.
|
let pci_node = fdt.begin_node(&pci_node_name)?;
|
||||||
let virtio_iommu_node_name = format!("virtio_iommu@{:x}", virtio_iommu_bdf);
|
|
||||||
let virtio_iommu_node = fdt.begin_node(&virtio_iommu_node_name)?;
|
|
||||||
fdt.property_u32("#iommu-cells", 1)?;
|
|
||||||
fdt.property_string("compatible", "virtio,pci-iommu")?;
|
|
||||||
|
|
||||||
// 'reg' is a five-cell address encoded as
|
fdt.property_string("compatible", "pci-host-ecam-generic")?;
|
||||||
// (phys.hi phys.mid phys.lo size.hi size.lo). phys.hi should contain the
|
fdt.property_string("device_type", "pci")?;
|
||||||
// device's BDF as 0b00000000 bbbbbbbb dddddfff 00000000. The other cells
|
fdt.property_array_u32("ranges", &ranges)?;
|
||||||
// should be zero.
|
fdt.property_array_u32("bus-range", &bus_range)?;
|
||||||
let reg = [virtio_iommu_bdf << 8, 0_u32, 0_u32, 0_u32, 0_u32];
|
fdt.property_u32(
|
||||||
fdt.property_array_u32("reg", ®)?;
|
"linux,pci-domain",
|
||||||
fdt.property_u32("phandle", VIRTIO_IOMMU_PHANDLE)?;
|
pci_device_info_elem.pci_segment_id as u32,
|
||||||
|
)?;
|
||||||
|
fdt.property_u32("#address-cells", 3)?;
|
||||||
|
fdt.property_u32("#size-cells", 2)?;
|
||||||
|
fdt.property_array_u64("reg", ®)?;
|
||||||
|
fdt.property_u32("#interrupt-cells", 1)?;
|
||||||
|
fdt.property_null("interrupt-map")?;
|
||||||
|
fdt.property_null("interrupt-map-mask")?;
|
||||||
|
fdt.property_null("dma-coherent")?;
|
||||||
|
fdt.property_array_u32("msi-map", &msi_map)?;
|
||||||
|
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
|
||||||
|
|
||||||
fdt.end_node(virtio_iommu_node)?;
|
if pci_device_info_elem.pci_segment_id == 0 {
|
||||||
|
if let Some(virtio_iommu_bdf) = virtio_iommu_bdf {
|
||||||
|
// See kernel document Documentation/devicetree/bindings/pci/pci-iommu.txt
|
||||||
|
// for 'iommu-map' attribute setting.
|
||||||
|
let iommu_map = [
|
||||||
|
0_u32,
|
||||||
|
VIRTIO_IOMMU_PHANDLE,
|
||||||
|
0_u32,
|
||||||
|
virtio_iommu_bdf,
|
||||||
|
virtio_iommu_bdf + 1,
|
||||||
|
VIRTIO_IOMMU_PHANDLE,
|
||||||
|
virtio_iommu_bdf + 1,
|
||||||
|
0xffff - virtio_iommu_bdf,
|
||||||
|
];
|
||||||
|
fdt.property_array_u32("iommu-map", &iommu_map)?;
|
||||||
|
|
||||||
|
// See kernel document Documentation/devicetree/bindings/virtio/iommu.txt
|
||||||
|
// for virtio-iommu node settings.
|
||||||
|
let virtio_iommu_node_name = format!("virtio_iommu@{:x}", virtio_iommu_bdf);
|
||||||
|
let virtio_iommu_node = fdt.begin_node(&virtio_iommu_node_name)?;
|
||||||
|
fdt.property_u32("#iommu-cells", 1)?;
|
||||||
|
fdt.property_string("compatible", "virtio,pci-iommu")?;
|
||||||
|
|
||||||
|
// 'reg' is a five-cell address encoded as
|
||||||
|
// (phys.hi phys.mid phys.lo size.hi size.lo). phys.hi should contain the
|
||||||
|
// device's BDF as 0b00000000 bbbbbbbb dddddfff 00000000. The other cells
|
||||||
|
// should be zero.
|
||||||
|
let reg = [virtio_iommu_bdf << 8, 0_u32, 0_u32, 0_u32, 0_u32];
|
||||||
|
fdt.property_array_u32("reg", ®)?;
|
||||||
|
fdt.property_u32("phandle", VIRTIO_IOMMU_PHANDLE)?;
|
||||||
|
|
||||||
|
fdt.end_node(virtio_iommu_node)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt.end_node(pci_node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt.end_node(pci_node)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ macro_rules! VGIC_DIST_REG {
|
|||||||
|
|
||||||
// List with relevant distributor registers that we will be restoring.
|
// List with relevant distributor registers that we will be restoring.
|
||||||
// Order is taken from qemu.
|
// Order is taken from qemu.
|
||||||
static VGIC_DIST_REGS: &'static [DistReg] = &[
|
static VGIC_DIST_REGS: &[DistReg] = &[
|
||||||
VGIC_DIST_REG!(GICD_STATUSR, 0, 4),
|
VGIC_DIST_REG!(GICD_STATUSR, 0, 4),
|
||||||
VGIC_DIST_REG!(GICD_ICENABLER, 1, 0),
|
VGIC_DIST_REG!(GICD_ICENABLER, 1, 0),
|
||||||
VGIC_DIST_REG!(GICD_ISENABLER, 1, 0),
|
VGIC_DIST_REG!(GICD_ISENABLER, 1, 0),
|
||||||
|
|||||||
@@ -124,12 +124,11 @@ pub mod kvm {
|
|||||||
its_device: &Arc<dyn hypervisor::Device>,
|
its_device: &Arc<dyn hypervisor::Device>,
|
||||||
save: bool,
|
save: bool,
|
||||||
) -> crate::aarch64::gic::Result<()> {
|
) -> crate::aarch64::gic::Result<()> {
|
||||||
let attr: u64;
|
let attr = if save {
|
||||||
if save {
|
u64::from(kvm_bindings::KVM_DEV_ARM_ITS_SAVE_TABLES)
|
||||||
attr = u64::from(kvm_bindings::KVM_DEV_ARM_ITS_SAVE_TABLES);
|
|
||||||
} else {
|
} else {
|
||||||
attr = u64::from(kvm_bindings::KVM_DEV_ARM_ITS_RESTORE_TABLES);
|
u64::from(kvm_bindings::KVM_DEV_ARM_ITS_RESTORE_TABLES)
|
||||||
}
|
};
|
||||||
|
|
||||||
let init_gic_attr = kvm_bindings::kvm_device_attr {
|
let init_gic_attr = kvm_bindings::kvm_device_attr {
|
||||||
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
|
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R1_EL1, 1);
|
|||||||
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R2_EL1, 2);
|
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R2_EL1, 2);
|
||||||
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R3_EL1, 3);
|
SYS_ICC_AP1Rn_EL1!(SYS_ICC_AP1R3_EL1, 3);
|
||||||
|
|
||||||
static VGIC_ICC_REGS: &'static [u64] = &[
|
static VGIC_ICC_REGS: &[u64] = &[
|
||||||
SYS_ICC_SRE_EL1,
|
SYS_ICC_SRE_EL1,
|
||||||
SYS_ICC_CTLR_EL1,
|
SYS_ICC_CTLR_EL1,
|
||||||
SYS_ICC_IGRPEN0_EL1,
|
SYS_ICC_IGRPEN0_EL1,
|
||||||
@@ -91,8 +91,7 @@ fn icc_attr_access(
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
};
|
};
|
||||||
if set {
|
if set {
|
||||||
#[allow(clippy::unnecessary_mut_passed)]
|
gic.set_device_attr(&gic_icc_attr)
|
||||||
gic.set_device_attr(&mut gic_icc_attr)
|
|
||||||
.map_err(Error::SetDeviceAttribute)?;
|
.map_err(Error::SetDeviceAttribute)?;
|
||||||
} else {
|
} else {
|
||||||
gic.get_device_attr(&mut gic_icc_attr)
|
gic.get_device_attr(&mut gic_icc_attr)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ macro_rules! VGIC_RDIST_REG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List with relevant distributor registers that we will be restoring.
|
// List with relevant distributor registers that we will be restoring.
|
||||||
static VGIC_RDIST_REGS: &'static [RdistReg] = &[
|
static VGIC_RDIST_REGS: &[RdistReg] = &[
|
||||||
VGIC_RDIST_REG!(GICR_STATUSR, 4),
|
VGIC_RDIST_REG!(GICR_STATUSR, 4),
|
||||||
VGIC_RDIST_REG!(GICR_WAKER, 4),
|
VGIC_RDIST_REG!(GICR_WAKER, 4),
|
||||||
VGIC_RDIST_REG!(GICR_PROPBASER, 8),
|
VGIC_RDIST_REG!(GICR_PROPBASER, 8),
|
||||||
@@ -70,7 +70,7 @@ static VGIC_RDIST_REGS: &'static [RdistReg] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
// List with relevant distributor registers that we will be restoring.
|
// List with relevant distributor registers that we will be restoring.
|
||||||
static VGIC_SGI_REGS: &'static [RdistReg] = &[
|
static VGIC_SGI_REGS: &[RdistReg] = &[
|
||||||
VGIC_RDIST_REG!(GICR_IGROUPR0, 4),
|
VGIC_RDIST_REG!(GICR_IGROUPR0, 4),
|
||||||
VGIC_RDIST_REG!(GICR_ICENABLER0, 4),
|
VGIC_RDIST_REG!(GICR_ICENABLER0, 4),
|
||||||
VGIC_RDIST_REG!(GICR_ISENABLER0, 4),
|
VGIC_RDIST_REG!(GICR_ISENABLER0, 4),
|
||||||
@@ -96,8 +96,7 @@ fn redist_attr_access(
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
};
|
};
|
||||||
if set {
|
if set {
|
||||||
#[allow(clippy::unnecessary_mut_passed)]
|
gic.set_device_attr(&gic_dist_attr)
|
||||||
gic.set_device_attr(&mut gic_dist_attr)
|
|
||||||
.map_err(Error::SetDeviceAttribute)?;
|
.map_err(Error::SetDeviceAttribute)?;
|
||||||
} else {
|
} else {
|
||||||
gic.get_device_attr(&mut gic_dist_attr)
|
gic.get_device_attr(&mut gic_dist_attr)
|
||||||
@@ -110,7 +109,7 @@ fn access_redists_aux(
|
|||||||
gic: &Arc<dyn hypervisor::Device>,
|
gic: &Arc<dyn hypervisor::Device>,
|
||||||
gicr_typer: &[u64],
|
gicr_typer: &[u64],
|
||||||
state: &mut Vec<u32>,
|
state: &mut Vec<u32>,
|
||||||
reg_list: &'static [RdistReg],
|
reg_list: &[RdistReg],
|
||||||
idx: &mut usize,
|
idx: &mut usize,
|
||||||
set: bool,
|
set: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x2000_0000;
|
|||||||
/// PCI MMCONFIG space (start: after the device space at 1 GiB, length: 256MiB)
|
/// PCI MMCONFIG space (start: after the device space at 1 GiB, length: 256MiB)
|
||||||
pub const PCI_MMCONFIG_START: GuestAddress = GuestAddress(0x3000_0000);
|
pub const PCI_MMCONFIG_START: GuestAddress = GuestAddress(0x3000_0000);
|
||||||
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
|
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
|
||||||
|
// One bus with potentially 256 devices (32 slots x 8 functions).
|
||||||
|
pub const PCI_MMIO_CONFIG_SIZE_PER_SEGMENT: u64 = 4096 * 256;
|
||||||
|
|
||||||
/// Start of RAM on 64 bit ARM.
|
/// Start of RAM on 64 bit ARM.
|
||||||
pub const RAM_64BIT_START: u64 = 0x4000_0000;
|
pub const RAM_64BIT_START: u64 = 0x4000_0000;
|
||||||
@@ -104,7 +106,7 @@ pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START);
|
|||||||
pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
|
pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
|
||||||
|
|
||||||
/// Pci high memory base
|
/// Pci high memory base
|
||||||
pub const PCI_HIGH_BASE: u64 = 0x80_0000_0000_u64;
|
pub const PCI_HIGH_BASE: u64 = 0x2_0000_0000_u64;
|
||||||
|
|
||||||
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
|
||||||
// the number of interrupts our GIC will support to be:
|
// the number of interrupts our GIC will support to be:
|
||||||
|
|||||||
@@ -14,16 +14,14 @@ pub mod regs;
|
|||||||
pub mod uefi;
|
pub mod uefi;
|
||||||
|
|
||||||
pub use self::fdt::DeviceInfoForFdt;
|
pub use self::fdt::DeviceInfoForFdt;
|
||||||
use crate::{DeviceType, GuestMemoryMmap, NumaNodes, RegionType};
|
use crate::{DeviceType, GuestMemoryMmap, NumaNodes, PciSpaceInfo, RegionType};
|
||||||
use gic::GicDevice;
|
use gic::GicDevice;
|
||||||
use log::{log_enabled, Level};
|
use log::{log_enabled, Level};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm_memory::{
|
use vm_memory::{Address, GuestAddress, GuestMemory, GuestUsize};
|
||||||
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestUsize,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Errors thrown while configuring aarch64 system.
|
/// Errors thrown while configuring aarch64 system.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -66,16 +64,10 @@ pub fn configure_vcpu(
|
|||||||
fd: &Arc<dyn hypervisor::Vcpu>,
|
fd: &Arc<dyn hypervisor::Vcpu>,
|
||||||
id: u8,
|
id: u8,
|
||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
|
||||||
) -> super::Result<u64> {
|
) -> super::Result<u64> {
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
regs::setup_regs(
|
regs::setup_regs(fd, id, kernel_entry_point.entry_addr.raw_value())
|
||||||
fd,
|
.map_err(Error::RegsConfiguration)?;
|
||||||
id,
|
|
||||||
kernel_entry_point.entry_addr.raw_value(),
|
|
||||||
&vm_memory.memory(),
|
|
||||||
)
|
|
||||||
.map_err(Error::RegsConfiguration)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mpidr = fd.read_mpidr().map_err(Error::VcpuRegMpidr)?;
|
let mpidr = fd.read_mpidr().map_err(Error::VcpuRegMpidr)?;
|
||||||
@@ -140,7 +132,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
|
|||||||
vcpu_topology: Option<(u8, u8, u8)>,
|
vcpu_topology: Option<(u8, u8, u8)>,
|
||||||
device_info: &HashMap<(DeviceType, String), T, S>,
|
device_info: &HashMap<(DeviceType, String), T, S>,
|
||||||
initrd: &Option<super::InitramfsConfig>,
|
initrd: &Option<super::InitramfsConfig>,
|
||||||
pci_space_address: &(u64, u64),
|
pci_space_info: &[PciSpaceInfo],
|
||||||
virtio_iommu_bdf: Option<u32>,
|
virtio_iommu_bdf: Option<u32>,
|
||||||
gic_device: &dyn GicDevice,
|
gic_device: &dyn GicDevice,
|
||||||
numa_nodes: &NumaNodes,
|
numa_nodes: &NumaNodes,
|
||||||
@@ -153,7 +145,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
|
|||||||
device_info,
|
device_info,
|
||||||
gic_device,
|
gic_device,
|
||||||
initrd,
|
initrd,
|
||||||
pci_space_address,
|
pci_space_info,
|
||||||
numa_nodes,
|
numa_nodes,
|
||||||
virtio_iommu_bdf,
|
virtio_iommu_bdf,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
use super::get_fdt_addr;
|
use super::get_fdt_addr;
|
||||||
use crate::GuestMemoryMmap;
|
|
||||||
use hypervisor::kvm::kvm_bindings::{
|
use hypervisor::kvm::kvm_bindings::{
|
||||||
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
|
||||||
};
|
};
|
||||||
@@ -43,12 +42,7 @@ const PSTATE_FAULT_BITS_64: u64 = PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_
|
|||||||
/// * `cpu_id` - Index of current vcpu.
|
/// * `cpu_id` - Index of current vcpu.
|
||||||
/// * `boot_ip` - Starting instruction pointer.
|
/// * `boot_ip` - Starting instruction pointer.
|
||||||
/// * `mem` - Reserved DRAM for current VM.
|
/// * `mem` - Reserved DRAM for current VM.
|
||||||
pub fn setup_regs(
|
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, cpu_id: u8, boot_ip: u64) -> Result<()> {
|
||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
|
||||||
cpu_id: u8,
|
|
||||||
boot_ip: u64,
|
|
||||||
_mem: &GuestMemoryMmap,
|
|
||||||
) -> Result<()> {
|
|
||||||
let kreg_off = offset__of!(kvm_regs, regs);
|
let kreg_off = offset__of!(kvm_regs, regs);
|
||||||
|
|
||||||
// Get the register index of the PSTATE (Processor State) register.
|
// Get the register index of the PSTATE (Processor State) register.
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
//! Implements platform specific functionality.
|
//! Implements platform specific functionality.
|
||||||
//! Supported platforms: x86_64, aarch64.
|
//! Supported platforms: x86_64, aarch64.
|
||||||
#![allow(clippy::transmute_ptr_to_ptr, clippy::redundant_static_lifetimes)]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
@@ -162,6 +161,16 @@ pub struct MmioDeviceInfo {
|
|||||||
pub irq: u32,
|
pub irq: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Structure to describe PCI space information
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub struct PciSpaceInfo {
|
||||||
|
pub pci_segment_id: u16,
|
||||||
|
pub mmio_config_address: u64,
|
||||||
|
pub pci_device_space_start: u64,
|
||||||
|
pub pci_device_space_size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
impl DeviceInfoForFdt for MmioDeviceInfo {
|
impl DeviceInfoForFdt for MmioDeviceInfo {
|
||||||
fn addr(&self) -> u64 {
|
fn addr(&self) -> u64 {
|
||||||
|
|||||||
@@ -95,22 +95,4 @@ mod tests {
|
|||||||
let mut klapic = LapicState::default();
|
let mut klapic = LapicState::default();
|
||||||
set_klapic_reg(&mut klapic, reg_offset, 3);
|
set_klapic_reg(&mut klapic, reg_offset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_apic_delivery_mode() {
|
|
||||||
let mut v: Vec<u32> = Vec::new();
|
|
||||||
v.resize(20, 0);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
libc::getrandom(v.as_mut_ptr() as *mut _ as *mut libc::c_void, 80, 0),
|
|
||||||
80
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
v.iter_mut()
|
|
||||||
.for_each(|x| *x = set_apic_delivery_mode(*x, 2));
|
|
||||||
let after: Vec<u32> = v.iter().map(|x| ((*x & !0x700) | ((2) << 8))).collect();
|
|
||||||
assert_eq!(v, after);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ pub const HIGH_RAM_START: GuestAddress = GuestAddress(0x100000);
|
|||||||
|
|
||||||
// == No fixed addresses in the "High RAM" range ==
|
// == No fixed addresses in the "High RAM" range ==
|
||||||
|
|
||||||
// ** 32-bit reserved area (start: 3GiB, length: 1GiB) **
|
// ** 32-bit reserved area (start: 3GiB, length: 896MiB) **
|
||||||
pub const MEM_32BIT_RESERVED_START: GuestAddress = GuestAddress(0xc000_0000);
|
pub const MEM_32BIT_RESERVED_START: GuestAddress = GuestAddress(0xc000_0000);
|
||||||
pub const MEM_32BIT_RESERVED_SIZE: u64 = 1024 << 20;
|
pub const MEM_32BIT_RESERVED_SIZE: u64 = PCI_MMCONFIG_SIZE + MEM_32BIT_DEVICES_SIZE;
|
||||||
|
|
||||||
// == Fixed constants within the "32-bit reserved" range ==
|
// == Fixed constants within the "32-bit reserved" range ==
|
||||||
|
|
||||||
@@ -93,6 +93,16 @@ pub const MEM_32BIT_DEVICES_SIZE: u64 = 640 << 20;
|
|||||||
pub const PCI_MMCONFIG_START: GuestAddress =
|
pub const PCI_MMCONFIG_START: GuestAddress =
|
||||||
GuestAddress(MEM_32BIT_DEVICES_START.0 + MEM_32BIT_DEVICES_SIZE);
|
GuestAddress(MEM_32BIT_DEVICES_START.0 + MEM_32BIT_DEVICES_SIZE);
|
||||||
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
|
pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20;
|
||||||
|
// One bus with potentially 256 devices (32 slots x 8 functions).
|
||||||
|
pub const PCI_MMIO_CONFIG_SIZE_PER_SEGMENT: u64 = 4096 * 256;
|
||||||
|
|
||||||
|
// TSS is 3 pages after the PCI MMCONFIG space
|
||||||
|
pub const KVM_TSS_START: GuestAddress = GuestAddress(PCI_MMCONFIG_START.0 + PCI_MMCONFIG_SIZE);
|
||||||
|
pub const KVM_TSS_SIZE: u64 = (3 * 4) << 10;
|
||||||
|
|
||||||
|
// Identity map is a one page region after the TSS
|
||||||
|
pub const KVM_IDENTITY_MAP_START: GuestAddress = GuestAddress(KVM_TSS_START.0 + KVM_TSS_SIZE);
|
||||||
|
pub const KVM_IDENTITY_MAP_SIZE: u64 = 4 << 10;
|
||||||
|
|
||||||
// IOAPIC
|
// IOAPIC
|
||||||
pub const IOAPIC_START: GuestAddress = GuestAddress(0xfec0_0000);
|
pub const IOAPIC_START: GuestAddress = GuestAddress(0xfec0_0000);
|
||||||
@@ -101,9 +111,6 @@ pub const IOAPIC_SIZE: u64 = 0x20;
|
|||||||
// APIC
|
// APIC
|
||||||
pub const APIC_START: GuestAddress = GuestAddress(0xfee0_0000);
|
pub const APIC_START: GuestAddress = GuestAddress(0xfee0_0000);
|
||||||
|
|
||||||
/// Address for the TSS setup.
|
|
||||||
pub const KVM_TSS_ADDRESS: GuestAddress = GuestAddress(0xfffb_d000);
|
|
||||||
|
|
||||||
// == End of "32-bit reserved" range. ==
|
// == End of "32-bit reserved" range. ==
|
||||||
|
|
||||||
// ** 64-bit RAM start (start: 4GiB, length: varies) **
|
// ** 64-bit RAM start (start: 4GiB, length: varies) **
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
|
|||||||
/// is to be used to configure the guest initial state.
|
/// is to be used to configure the guest initial state.
|
||||||
pub struct EntryPoint {
|
pub struct EntryPoint {
|
||||||
/// Address in guest memory where the guest must start execution
|
/// Address in guest memory where the guest must start execution
|
||||||
pub entry_addr: GuestAddress,
|
pub entry_addr: Option<GuestAddress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const E820_RAM: u32 = 1;
|
const E820_RAM: u32 = 1;
|
||||||
@@ -118,17 +118,15 @@ impl SgxEpcRegion {
|
|||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct StartInfoWrapper(hvm_start_info);
|
struct StartInfoWrapper(hvm_start_info);
|
||||||
|
|
||||||
// It is safe to initialize StartInfoWrapper which is a wrapper over `hvm_start_info` (a series of ints).
|
|
||||||
unsafe impl ByteValued for StartInfoWrapper {}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
|
struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
|
||||||
|
|
||||||
unsafe impl ByteValued for MemmapTableEntryWrapper {}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct ModlistEntryWrapper(hvm_modlist_entry);
|
struct ModlistEntryWrapper(hvm_modlist_entry);
|
||||||
|
|
||||||
|
// SAFETY: These data structures only contain a series of integers
|
||||||
|
unsafe impl ByteValued for StartInfoWrapper {}
|
||||||
|
unsafe impl ByteValued for MemmapTableEntryWrapper {}
|
||||||
unsafe impl ByteValued for ModlistEntryWrapper {}
|
unsafe impl ByteValued for ModlistEntryWrapper {}
|
||||||
|
|
||||||
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
||||||
@@ -139,7 +137,7 @@ unsafe impl ByteValued for ModlistEntryWrapper {}
|
|||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct BootParamsWrapper(boot_params);
|
struct BootParamsWrapper(boot_params);
|
||||||
|
|
||||||
// It is safe to initialize BootParamsWrap which is a wrapper over `boot_params` (a series of ints).
|
// SAFETY: BootParamsWrap is a wrapper over `boot_params` (a series of ints).
|
||||||
unsafe impl ByteValued for BootParamsWrapper {}
|
unsafe impl ByteValued for BootParamsWrapper {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -317,21 +315,12 @@ impl CpuidPatch {
|
|||||||
|
|
||||||
for entry in entries.iter() {
|
for entry in entries.iter() {
|
||||||
if entry.function == function && entry.index == index {
|
if entry.function == function && entry.index == index {
|
||||||
let reg_val: u32;
|
let reg_val = match reg {
|
||||||
match reg {
|
CpuidReg::EAX => entry.eax,
|
||||||
CpuidReg::EAX => {
|
CpuidReg::EBX => entry.ebx,
|
||||||
reg_val = entry.eax;
|
CpuidReg::ECX => entry.ecx,
|
||||||
}
|
CpuidReg::EDX => entry.edx,
|
||||||
CpuidReg::EBX => {
|
};
|
||||||
reg_val = entry.ebx;
|
|
||||||
}
|
|
||||||
CpuidReg::ECX => {
|
|
||||||
reg_val = entry.ecx;
|
|
||||||
}
|
|
||||||
CpuidReg::EDX => {
|
|
||||||
reg_val = entry.edx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (reg_val & mask) == mask;
|
return (reg_val & mask) == mask;
|
||||||
}
|
}
|
||||||
@@ -524,19 +513,14 @@ impl CpuidFeatureEntry {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let entry = &feature_entry_list[i];
|
let entry = &feature_entry_list[i];
|
||||||
let entry_compatible;
|
let entry_compatible = match entry.compatible_check {
|
||||||
match entry.compatible_check {
|
|
||||||
CpuidCompatibleCheck::BitwiseSubset => {
|
CpuidCompatibleCheck::BitwiseSubset => {
|
||||||
let different_feature_bits = src_vm_feature ^ dest_vm_feature;
|
let different_feature_bits = src_vm_feature ^ dest_vm_feature;
|
||||||
let src_vm_feature_bits_only = different_feature_bits & src_vm_feature;
|
let src_vm_feature_bits_only = different_feature_bits & src_vm_feature;
|
||||||
entry_compatible = src_vm_feature_bits_only == 0;
|
src_vm_feature_bits_only == 0
|
||||||
}
|
|
||||||
CpuidCompatibleCheck::Equal => {
|
|
||||||
entry_compatible = src_vm_feature == dest_vm_feature;
|
|
||||||
}
|
|
||||||
CpuidCompatibleCheck::NumNotGreater => {
|
|
||||||
entry_compatible = src_vm_feature <= dest_vm_feature;
|
|
||||||
}
|
}
|
||||||
|
CpuidCompatibleCheck::Equal => src_vm_feature == dest_vm_feature,
|
||||||
|
CpuidCompatibleCheck::NumNotGreater => src_vm_feature <= dest_vm_feature,
|
||||||
};
|
};
|
||||||
if !entry_compatible {
|
if !entry_compatible {
|
||||||
error!(
|
error!(
|
||||||
@@ -743,11 +727,12 @@ pub fn configure_vcpu(
|
|||||||
|
|
||||||
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
if let Some(entry_addr) = kernel_entry_point.entry_addr {
|
||||||
regs::setup_regs(fd, kernel_entry_point.entry_addr.raw_value())
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
.map_err(Error::RegsConfiguration)?;
|
regs::setup_regs(fd, entry_addr.raw_value()).map_err(Error::RegsConfiguration)?;
|
||||||
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
||||||
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
|
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct MpcLintsrcWrapper(mpspec::mpc_lintsrc);
|
|||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct MpfIntelWrapper(mpspec::mpf_intel);
|
struct MpfIntelWrapper(mpspec::mpf_intel);
|
||||||
|
|
||||||
// These `mpspec` wrapper types are only data, reading them from data is a safe initialization.
|
// SAFETY: These `mpspec` wrapper types are only data, reading them from data is a safe initialization.
|
||||||
unsafe impl ByteValued for MpcBusWrapper {}
|
unsafe impl ByteValued for MpcBusWrapper {}
|
||||||
unsafe impl ByteValued for MpcCpuWrapper {}
|
unsafe impl ByteValued for MpcCpuWrapper {}
|
||||||
unsafe impl ByteValued for MpcIntsrcWrapper {}
|
unsafe impl ByteValued for MpcIntsrcWrapper {}
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ pub struct Smbios30Entrypoint {
|
|||||||
pub max_size: u32,
|
pub max_size: u32,
|
||||||
pub physptr: u64,
|
pub physptr: u64,
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for Smbios30Entrypoint {}
|
|
||||||
|
|
||||||
impl Clone for Smbios30Entrypoint {
|
impl Clone for Smbios30Entrypoint {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
@@ -112,8 +111,6 @@ impl Clone for SmbiosBiosInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl ByteValued for SmbiosBiosInfo {}
|
|
||||||
|
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
#[derive(Default, Copy)]
|
#[derive(Default, Copy)]
|
||||||
pub struct SmbiosSysInfo {
|
pub struct SmbiosSysInfo {
|
||||||
@@ -136,6 +133,9 @@ impl Clone for SmbiosSysInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: These data structures only contain a series of integers
|
||||||
|
unsafe impl ByteValued for Smbios30Entrypoint {}
|
||||||
|
unsafe impl ByteValued for SmbiosBiosInfo {}
|
||||||
unsafe impl ByteValued for SmbiosSysInfo {}
|
unsafe impl ByteValued for SmbiosSysInfo {}
|
||||||
|
|
||||||
fn write_and_incr<T: ByteValued>(
|
fn write_and_incr<T: ByteValued>(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub enum TdvfError {
|
|||||||
|
|
||||||
// TDVF_DESCRIPTOR
|
// TDVF_DESCRIPTOR
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
|
#[derive(Default)]
|
||||||
pub struct TdvfDescriptor {
|
pub struct TdvfDescriptor {
|
||||||
signature: [u8; 4],
|
signature: [u8; 4],
|
||||||
length: u32,
|
length: u32,
|
||||||
@@ -68,8 +69,6 @@ pub struct TdVmmDataRegion {
|
|||||||
pub region_type: TdVmmDataRegionType,
|
pub region_type: TdVmmDataRegionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl ByteValued for TdVmmDataRegion {}
|
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum TdVmmDataRegionType {
|
pub enum TdVmmDataRegionType {
|
||||||
@@ -128,7 +127,7 @@ pub fn parse_tdvf_sections(file: &mut File) -> Result<Vec<TdvfSection>, TdvfErro
|
|||||||
file.seek(SeekFrom::Start(descriptor_offset))
|
file.seek(SeekFrom::Start(descriptor_offset))
|
||||||
.map_err(TdvfError::ReadDescriptor)?;
|
.map_err(TdvfError::ReadDescriptor)?;
|
||||||
|
|
||||||
let mut descriptor: TdvfDescriptor = unsafe { std::mem::zeroed() };
|
let mut descriptor: TdvfDescriptor = Default::default();
|
||||||
// Safe as we read exactly the size of the descriptor header
|
// Safe as we read exactly the size of the descriptor header
|
||||||
file.read_exact(unsafe {
|
file.read_exact(unsafe {
|
||||||
std::slice::from_raw_parts_mut(
|
std::slice::from_raw_parts_mut(
|
||||||
@@ -191,7 +190,6 @@ struct HobHeader {
|
|||||||
length: u16,
|
length: u16,
|
||||||
reserved: u32,
|
reserved: u32,
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for HobHeader {}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
@@ -205,7 +203,6 @@ struct HobHandoffInfoTable {
|
|||||||
efi_free_memory_bottom: u64,
|
efi_free_memory_bottom: u64,
|
||||||
efi_end_of_hob_list: u64,
|
efi_end_of_hob_list: u64,
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for HobHandoffInfoTable {}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
@@ -226,7 +223,6 @@ struct HobResourceDescriptor {
|
|||||||
physical_start: u64,
|
physical_start: u64,
|
||||||
resource_length: u64,
|
resource_length: u64,
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for HobResourceDescriptor {}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
@@ -234,7 +230,6 @@ struct HobGuidType {
|
|||||||
header: HobHeader,
|
header: HobHeader,
|
||||||
name: EfiGuid,
|
name: EfiGuid,
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for HobGuidType {}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
@@ -242,6 +237,13 @@ struct TdVmmData {
|
|||||||
guid_type: HobGuidType,
|
guid_type: HobGuidType,
|
||||||
region: TdVmmDataRegion,
|
region: TdVmmDataRegion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: These data structures only contain a series of integers
|
||||||
|
unsafe impl ByteValued for TdVmmDataRegion {}
|
||||||
|
unsafe impl ByteValued for HobHeader {}
|
||||||
|
unsafe impl ByteValued for HobHandoffInfoTable {}
|
||||||
|
unsafe impl ByteValued for HobResourceDescriptor {}
|
||||||
|
unsafe impl ByteValued for HobGuidType {}
|
||||||
unsafe impl ByteValued for TdVmmData {}
|
unsafe impl ByteValued for TdVmmData {}
|
||||||
|
|
||||||
pub struct TdHob {
|
pub struct TdHob {
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ edition = "2018"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
io_uring = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
io-uring = "0.5.2"
|
io-uring = "0.5.2"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
@@ -18,7 +17,8 @@ versionize = "0.1.6"
|
|||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vhdx = { path = "../vhdx" }
|
vhdx = { path = "../vhdx" }
|
||||||
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
|
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
|
||||||
vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
virtio-queue = { path = "../virtio-queue" }
|
||||||
|
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,13 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
|
use libc::{ioctl, S_IFBLK, S_IFMT};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
use vmm_sys_util::{ioctl_expr, ioctl_io_nr, ioctl_ioc_nr};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum DiskFileError {
|
pub enum DiskFileError {
|
||||||
@@ -15,11 +20,96 @@ pub enum DiskFileError {
|
|||||||
NewAsyncIo(#[source] std::io::Error),
|
NewAsyncIo(#[source] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DiskTopology {
|
||||||
|
pub logical_block_size: u64,
|
||||||
|
pub physical_block_size: u64,
|
||||||
|
pub minimum_io_size: u64,
|
||||||
|
pub optimal_io_size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DiskTopology {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
logical_block_size: 512,
|
||||||
|
physical_block_size: 512,
|
||||||
|
minimum_io_size: 512,
|
||||||
|
optimal_io_size: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl_io_nr!(BLKSSZGET, 0x12, 104);
|
||||||
|
ioctl_io_nr!(BLKPBSZGET, 0x12, 123);
|
||||||
|
ioctl_io_nr!(BLKIOMIN, 0x12, 120);
|
||||||
|
ioctl_io_nr!(BLKIOOPT, 0x12, 121);
|
||||||
|
|
||||||
|
enum BlockSize {
|
||||||
|
LogicalBlock,
|
||||||
|
PhysicalBlock,
|
||||||
|
MinimumIo,
|
||||||
|
OptimalIo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DiskTopology {
|
||||||
|
fn is_block_device(f: &mut File) -> std::io::Result<bool> {
|
||||||
|
let mut stat = std::mem::MaybeUninit::<libc::stat>::uninit();
|
||||||
|
let ret = unsafe { libc::fstat(f.as_raw_fd(), stat.as_mut_ptr()) };
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_block = unsafe { (*stat.as_ptr()).st_mode & S_IFMT == S_IFBLK };
|
||||||
|
Ok(is_block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// libc::ioctl() takes different types on different architectures
|
||||||
|
#[allow(clippy::useless_conversion)]
|
||||||
|
fn query_block_size(f: &mut File, block_size_type: BlockSize) -> std::io::Result<u64> {
|
||||||
|
let mut block_size = 0;
|
||||||
|
let ret = unsafe {
|
||||||
|
ioctl(
|
||||||
|
f.as_raw_fd(),
|
||||||
|
match block_size_type {
|
||||||
|
BlockSize::LogicalBlock => BLKSSZGET(),
|
||||||
|
BlockSize::PhysicalBlock => BLKPBSZGET(),
|
||||||
|
BlockSize::MinimumIo => BLKIOMIN(),
|
||||||
|
BlockSize::OptimalIo => BLKIOOPT(),
|
||||||
|
}
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
&mut block_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ret != 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(block_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn probe(f: &mut File) -> std::io::Result<Self> {
|
||||||
|
if !Self::is_block_device(f)? {
|
||||||
|
return Ok(DiskTopology::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(DiskTopology {
|
||||||
|
logical_block_size: Self::query_block_size(f, BlockSize::LogicalBlock)?,
|
||||||
|
physical_block_size: Self::query_block_size(f, BlockSize::PhysicalBlock)?,
|
||||||
|
minimum_io_size: Self::query_block_size(f, BlockSize::MinimumIo)?,
|
||||||
|
optimal_io_size: Self::query_block_size(f, BlockSize::OptimalIo)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
|
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
|
||||||
|
|
||||||
pub trait DiskFile: Send + Sync {
|
pub trait DiskFile: Send + Sync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64>;
|
fn size(&mut self) -> DiskFileResult<u64>;
|
||||||
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>;
|
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>;
|
||||||
|
fn topology(&mut self) -> DiskTopology {
|
||||||
|
DiskTopology::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|||||||
@@ -20,27 +20,25 @@ pub mod raw_sync;
|
|||||||
pub mod vhd;
|
pub mod vhd;
|
||||||
pub mod vhdx_sync;
|
pub mod vhdx_sync;
|
||||||
|
|
||||||
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, DiskFileError, DiskFileResult};
|
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
||||||
#[cfg(feature = "io_uring")]
|
|
||||||
use io_uring::{opcode, IoUring, Probe};
|
use io_uring::{opcode, IoUring, Probe};
|
||||||
|
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
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;
|
||||||
#[cfg(feature = "io_uring")]
|
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::MutexGuard;
|
||||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||||
use versionize_derive::Versionize;
|
use versionize_derive::Versionize;
|
||||||
use virtio_bindings::bindings::virtio_blk::*;
|
use virtio_bindings::bindings::virtio_blk::*;
|
||||||
|
use virtio_queue::DescriptorChain;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
|
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
|
||||||
GuestMemoryError,
|
GuestMemoryError, GuestMemoryLoadGuard,
|
||||||
};
|
};
|
||||||
use vm_virtio::DescriptorChain;
|
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||||
@@ -115,6 +113,8 @@ pub enum ExecuteError {
|
|||||||
AsyncRead(AsyncIoError),
|
AsyncRead(AsyncIoError),
|
||||||
AsyncWrite(AsyncIoError),
|
AsyncWrite(AsyncIoError),
|
||||||
AsyncFlush(AsyncIoError),
|
AsyncFlush(AsyncIoError),
|
||||||
|
/// Failed allocating a temporary buffer.
|
||||||
|
TemporaryBufferAllocation(io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecuteError {
|
impl ExecuteError {
|
||||||
@@ -131,6 +131,7 @@ impl ExecuteError {
|
|||||||
ExecuteError::AsyncRead(_) => VIRTIO_BLK_S_IOERR,
|
ExecuteError::AsyncRead(_) => VIRTIO_BLK_S_IOERR,
|
||||||
ExecuteError::AsyncWrite(_) => VIRTIO_BLK_S_IOERR,
|
ExecuteError::AsyncWrite(_) => VIRTIO_BLK_S_IOERR,
|
||||||
ExecuteError::AsyncFlush(_) => VIRTIO_BLK_S_IOERR,
|
ExecuteError::AsyncFlush(_) => VIRTIO_BLK_S_IOERR,
|
||||||
|
ExecuteError::TemporaryBufferAllocation(_) => VIRTIO_BLK_S_IOERR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,6 +169,14 @@ fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64,
|
|||||||
mem.read_obj(addr).map_err(Error::GuestMemory)
|
mem.read_obj(addr).map_err(Error::GuestMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AlignedOperation {
|
||||||
|
origin_ptr: u64,
|
||||||
|
aligned_ptr: u64,
|
||||||
|
size: usize,
|
||||||
|
layout: Layout,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
pub request_type: RequestType,
|
pub request_type: RequestType,
|
||||||
@@ -175,29 +184,38 @@ pub struct Request {
|
|||||||
pub data_descriptors: Vec<(GuestAddress, u32)>,
|
pub data_descriptors: Vec<(GuestAddress, u32)>,
|
||||||
pub status_addr: GuestAddress,
|
pub status_addr: GuestAddress,
|
||||||
pub writeback: bool,
|
pub writeback: bool,
|
||||||
|
pub aligned_operations: Vec<AlignedOperation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
avail_desc: &DescriptorChain,
|
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap>>,
|
||||||
mem: &GuestMemoryMmap,
|
|
||||||
) -> result::Result<Request, Error> {
|
) -> result::Result<Request, Error> {
|
||||||
|
let hdr_desc = desc_chain
|
||||||
|
.next()
|
||||||
|
.ok_or(Error::DescriptorChainTooShort)
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("Missing head descriptor");
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
// The head contains the request type which MUST be readable.
|
// The head contains the request type which MUST be readable.
|
||||||
if avail_desc.is_write_only() {
|
if hdr_desc.is_write_only() {
|
||||||
return Err(Error::UnexpectedWriteOnlyDescriptor);
|
return Err(Error::UnexpectedWriteOnlyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut req = Request {
|
let mut req = Request {
|
||||||
request_type: request_type(mem, avail_desc.addr)?,
|
request_type: request_type(desc_chain.memory(), hdr_desc.addr())?,
|
||||||
sector: sector(mem, avail_desc.addr)?,
|
sector: sector(desc_chain.memory(), hdr_desc.addr())?,
|
||||||
data_descriptors: Vec::new(),
|
data_descriptors: Vec::new(),
|
||||||
status_addr: GuestAddress(0),
|
status_addr: GuestAddress(0),
|
||||||
writeback: true,
|
writeback: true,
|
||||||
|
aligned_operations: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let status_desc;
|
let status_desc;
|
||||||
let mut desc = avail_desc
|
let mut desc = desc_chain
|
||||||
.next_descriptor()
|
.next()
|
||||||
.ok_or(Error::DescriptorChainTooShort)
|
.ok_or(Error::DescriptorChainTooShort)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Only head descriptor present: request = {:?}", req);
|
error!("Only head descriptor present: request = {:?}", req);
|
||||||
@@ -222,9 +240,9 @@ impl Request {
|
|||||||
if !desc.is_write_only() && req.request_type == RequestType::GetDeviceId {
|
if !desc.is_write_only() && req.request_type == RequestType::GetDeviceId {
|
||||||
return Err(Error::UnexpectedReadOnlyDescriptor);
|
return Err(Error::UnexpectedReadOnlyDescriptor);
|
||||||
}
|
}
|
||||||
req.data_descriptors.push((desc.addr, desc.len));
|
req.data_descriptors.push((desc.addr(), desc.len()));
|
||||||
desc = desc
|
desc = desc_chain
|
||||||
.next_descriptor()
|
.next()
|
||||||
.ok_or(Error::DescriptorChainTooShort)
|
.ok_or(Error::DescriptorChainTooShort)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("DescriptorChain corrupted: request = {:?}", req);
|
error!("DescriptorChain corrupted: request = {:?}", req);
|
||||||
@@ -239,22 +257,21 @@ impl Request {
|
|||||||
return Err(Error::UnexpectedReadOnlyDescriptor);
|
return Err(Error::UnexpectedReadOnlyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if status_desc.len < 1 {
|
if status_desc.len() < 1 {
|
||||||
return Err(Error::DescriptorLengthTooSmall);
|
return Err(Error::DescriptorLengthTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
req.status_addr = status_desc.addr;
|
req.status_addr = status_desc.addr();
|
||||||
|
|
||||||
Ok(req)
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
pub fn execute<T: Seek + Read + Write>(
|
pub fn execute<T: Seek + Read + Write>(
|
||||||
&self,
|
&self,
|
||||||
disk: &mut T,
|
disk: &mut T,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
disk_id: &Vec<u8>,
|
disk_id: &[u8],
|
||||||
) -> result::Result<u32, ExecuteError> {
|
) -> result::Result<u32, ExecuteError> {
|
||||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||||
.map_err(ExecuteError::Seek)?;
|
.map_err(ExecuteError::Seek)?;
|
||||||
@@ -289,7 +306,7 @@ impl Request {
|
|||||||
if (*data_len as usize) < disk_id.len() {
|
if (*data_len as usize) < disk_id.len() {
|
||||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||||
}
|
}
|
||||||
mem.write_slice(disk_id.as_slice(), *data_addr)
|
mem.write_slice(disk_id, *data_addr)
|
||||||
.map_err(ExecuteError::Write)?;
|
.map_err(ExecuteError::Write)?;
|
||||||
}
|
}
|
||||||
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
||||||
@@ -299,7 +316,7 @@ impl Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_async(
|
pub fn execute_async(
|
||||||
&self,
|
&mut self,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
disk_image: &mut dyn AsyncIo,
|
disk_image: &mut dyn AsyncIo,
|
||||||
@@ -312,6 +329,9 @@ impl Request {
|
|||||||
|
|
||||||
let mut iovecs = Vec::new();
|
let mut iovecs = Vec::new();
|
||||||
for (data_addr, data_len) in &self.data_descriptors {
|
for (data_addr, data_len) in &self.data_descriptors {
|
||||||
|
if *data_len == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let mut top: u64 = u64::from(*data_len) / SECTOR_SIZE;
|
let mut top: u64 = u64::from(*data_len) / SECTOR_SIZE;
|
||||||
if u64::from(*data_len) % SECTOR_SIZE != 0 {
|
if u64::from(*data_len) % SECTOR_SIZE != 0 {
|
||||||
top += 1;
|
top += 1;
|
||||||
@@ -323,12 +343,52 @@ impl Request {
|
|||||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
let buf = mem
|
let origin_ptr = mem
|
||||||
.get_slice(*data_addr, *data_len as usize)
|
.get_slice(*data_addr, *data_len as usize)
|
||||||
.map_err(ExecuteError::GetHostAddress)?
|
.map_err(ExecuteError::GetHostAddress)?
|
||||||
.as_ptr();
|
.as_ptr();
|
||||||
|
|
||||||
|
// Verify the buffer alignment.
|
||||||
|
// In case it's not properly aligned, an intermediate buffer is
|
||||||
|
// created with the correct alignment, and a copy from/to the
|
||||||
|
// origin buffer is performed, depending on the type of operation.
|
||||||
|
let iov_base = if (origin_ptr as u64) % SECTOR_SIZE != 0 {
|
||||||
|
let layout =
|
||||||
|
Layout::from_size_align(*data_len as usize, SECTOR_SIZE as usize).unwrap();
|
||||||
|
// Safe because layout has non-zero size
|
||||||
|
let aligned_ptr = unsafe { alloc_zeroed(layout) };
|
||||||
|
if aligned_ptr.is_null() {
|
||||||
|
return Err(ExecuteError::TemporaryBufferAllocation(
|
||||||
|
io::Error::last_os_error(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to perform the copy beforehand in case we're writing
|
||||||
|
// data out.
|
||||||
|
if request_type == RequestType::Out {
|
||||||
|
// Safe because destination buffer has been allocated with
|
||||||
|
// the proper size.
|
||||||
|
unsafe {
|
||||||
|
std::ptr::copy(origin_ptr as *const u8, aligned_ptr, *data_len as usize)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store both origin and aligned pointers for complete_async()
|
||||||
|
// to process them.
|
||||||
|
self.aligned_operations.push(AlignedOperation {
|
||||||
|
origin_ptr: origin_ptr as u64,
|
||||||
|
aligned_ptr: aligned_ptr as u64,
|
||||||
|
size: *data_len as usize,
|
||||||
|
layout,
|
||||||
|
});
|
||||||
|
|
||||||
|
aligned_ptr as *mut libc::c_void
|
||||||
|
} else {
|
||||||
|
origin_ptr as *mut libc::c_void
|
||||||
|
};
|
||||||
|
|
||||||
let iovec = libc::iovec {
|
let iovec = libc::iovec {
|
||||||
iov_base: buf as *mut libc::c_void,
|
iov_base,
|
||||||
iov_len: *data_len as libc::size_t,
|
iov_len: *data_len as libc::size_t,
|
||||||
};
|
};
|
||||||
iovecs.push(iovec);
|
iovecs.push(iovec);
|
||||||
@@ -376,6 +436,36 @@ impl Request {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn complete_async(&mut self) -> result::Result<(), Error> {
|
||||||
|
for aligned_operation in self.aligned_operations.drain(..) {
|
||||||
|
// We need to perform the copy after the data has been read inside
|
||||||
|
// the aligned buffer in case we're reading data in.
|
||||||
|
if self.request_type == RequestType::In {
|
||||||
|
// Safe because origin buffer has been allocated with the
|
||||||
|
// proper size.
|
||||||
|
unsafe {
|
||||||
|
std::ptr::copy(
|
||||||
|
aligned_operation.aligned_ptr as *const u8,
|
||||||
|
aligned_operation.origin_ptr as *mut u8,
|
||||||
|
aligned_operation.size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the temporary aligned buffer.
|
||||||
|
// Safe because aligned_ptr was allocated by alloc_zeroed with the same
|
||||||
|
// layout
|
||||||
|
unsafe {
|
||||||
|
dealloc(
|
||||||
|
aligned_operation.aligned_ptr as *mut u8,
|
||||||
|
aligned_operation.layout,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_writeback(&mut self, writeback: bool) {
|
pub fn set_writeback(&mut self, writeback: bool) {
|
||||||
self.writeback = writeback
|
self.writeback = writeback
|
||||||
}
|
}
|
||||||
@@ -404,8 +494,6 @@ pub struct VirtioBlockConfig {
|
|||||||
pub write_zeroes_may_unmap: u8,
|
pub write_zeroes_may_unmap: u8,
|
||||||
pub unused1: [u8; 3],
|
pub unused1: [u8; 3],
|
||||||
}
|
}
|
||||||
unsafe impl ByteValued for VirtioBlockConfig {}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct VirtioBlockGeometry {
|
pub struct VirtioBlockGeometry {
|
||||||
@@ -413,11 +501,13 @@ pub struct VirtioBlockGeometry {
|
|||||||
pub heads: u8,
|
pub heads: u8,
|
||||||
pub sectors: u8,
|
pub sectors: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: these data structures only contain a series of integers
|
||||||
|
unsafe impl ByteValued for VirtioBlockConfig {}
|
||||||
unsafe impl ByteValued for VirtioBlockGeometry {}
|
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.
|
||||||
#[cfg(feature = "io_uring")]
|
|
||||||
pub fn block_io_uring_is_supported() -> bool {
|
pub fn block_io_uring_is_supported() -> bool {
|
||||||
let error_msg = "io_uring not supported:";
|
let error_msg = "io_uring not supported:";
|
||||||
|
|
||||||
@@ -433,25 +523,6 @@ pub fn block_io_uring_is_supported() -> bool {
|
|||||||
|
|
||||||
let submitter = io_uring.submitter();
|
let submitter = io_uring.submitter();
|
||||||
|
|
||||||
let event_fd = match EventFd::new(libc::EFD_NONBLOCK) {
|
|
||||||
Ok(fd) => fd,
|
|
||||||
Err(e) => {
|
|
||||||
info!("{} failed to create eventfd: {}", error_msg, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check we can register an eventfd as this is going to be needed while
|
|
||||||
// using io_uring with the virtio block device. This also validates that
|
|
||||||
// io_uring_register() syscall is supported.
|
|
||||||
match submitter.register_eventfd(event_fd.as_raw_fd()) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
info!("{} failed to register eventfd: {}", error_msg, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut probe = Probe::new();
|
let mut probe = Probe::new();
|
||||||
|
|
||||||
// Check we can register a probe to validate supported operations.
|
// Check we can register a probe to validate supported operations.
|
||||||
@@ -484,119 +555,98 @@ pub fn block_io_uring_is_supported() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "io_uring"))]
|
pub trait AsyncAdaptor<F>
|
||||||
pub fn block_io_uring_is_supported() -> bool {
|
where
|
||||||
false
|
F: Read + Write + Seek,
|
||||||
}
|
{
|
||||||
|
fn read_vectored_sync(
|
||||||
|
&mut self,
|
||||||
|
offset: libc::off_t,
|
||||||
|
iovecs: Vec<libc::iovec>,
|
||||||
|
user_data: u64,
|
||||||
|
eventfd: &EventFd,
|
||||||
|
completion_list: &mut Vec<(u64, i32)>,
|
||||||
|
) -> AsyncIoResult<()> {
|
||||||
|
// Convert libc::iovec into IoSliceMut
|
||||||
|
let mut slices = Vec::new();
|
||||||
|
for iovec in iovecs.iter() {
|
||||||
|
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn disk_size(file: &mut dyn Seek, semaphore: &mut Arc<Mutex<()>>) -> DiskFileResult<u64> {
|
let result = {
|
||||||
// Take the semaphore to ensure other threads are not interacting with
|
let mut file = self.file();
|
||||||
// the underlying file.
|
|
||||||
let _lock = semaphore.lock().unwrap();
|
|
||||||
|
|
||||||
Ok(file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size)? as u64)
|
// Move the cursor to the right offset
|
||||||
}
|
file.seek(SeekFrom::Start(offset as u64))
|
||||||
|
.map_err(AsyncIoError::ReadVectored)?;
|
||||||
|
|
||||||
pub trait ReadSeekFile: Read + Seek {}
|
// Read vectored
|
||||||
impl<F: Read + Seek> ReadSeekFile for F {}
|
file.read_vectored(slices.as_mut_slice())
|
||||||
|
.map_err(AsyncIoError::ReadVectored)?
|
||||||
|
};
|
||||||
|
|
||||||
pub fn read_vectored_sync(
|
completion_list.push((user_data, result as i32));
|
||||||
offset: libc::off_t,
|
|
||||||
iovecs: Vec<libc::iovec>,
|
|
||||||
user_data: u64,
|
|
||||||
file: &mut dyn ReadSeekFile,
|
|
||||||
eventfd: &EventFd,
|
|
||||||
completion_list: &mut Vec<(u64, i32)>,
|
|
||||||
semaphore: &mut Arc<Mutex<()>>,
|
|
||||||
) -> AsyncIoResult<()> {
|
|
||||||
// Convert libc::iovec into IoSliceMut
|
|
||||||
let mut slices = Vec::new();
|
|
||||||
for iovec in iovecs.iter() {
|
|
||||||
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = {
|
|
||||||
// Take the semaphore to ensure other threads are not interacting
|
|
||||||
// with the underlying file.
|
|
||||||
let _lock = semaphore.lock().unwrap();
|
|
||||||
|
|
||||||
// Move the cursor to the right offset
|
|
||||||
file.seek(SeekFrom::Start(offset as u64))
|
|
||||||
.map_err(AsyncIoError::ReadVectored)?;
|
|
||||||
|
|
||||||
// Read vectored
|
|
||||||
file.read_vectored(slices.as_mut_slice())
|
|
||||||
.map_err(AsyncIoError::ReadVectored)?
|
|
||||||
};
|
|
||||||
|
|
||||||
completion_list.push((user_data, result as i32));
|
|
||||||
eventfd.write(1).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait WriteSeekFile: Write + Seek {}
|
|
||||||
impl<F: Write + Seek> WriteSeekFile for F {}
|
|
||||||
|
|
||||||
pub fn write_vectored_sync(
|
|
||||||
offset: libc::off_t,
|
|
||||||
iovecs: Vec<libc::iovec>,
|
|
||||||
user_data: u64,
|
|
||||||
file: &mut dyn WriteSeekFile,
|
|
||||||
eventfd: &EventFd,
|
|
||||||
completion_list: &mut Vec<(u64, i32)>,
|
|
||||||
semaphore: &mut Arc<Mutex<()>>,
|
|
||||||
) -> AsyncIoResult<()> {
|
|
||||||
// Convert libc::iovec into IoSlice
|
|
||||||
let mut slices = Vec::new();
|
|
||||||
for iovec in iovecs.iter() {
|
|
||||||
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = {
|
|
||||||
// Take the semaphore to ensure other threads are not interacting
|
|
||||||
// with the underlying file.
|
|
||||||
let _lock = semaphore.lock().unwrap();
|
|
||||||
|
|
||||||
// Move the cursor to the right offset
|
|
||||||
file.seek(SeekFrom::Start(offset as u64))
|
|
||||||
.map_err(AsyncIoError::WriteVectored)?;
|
|
||||||
|
|
||||||
// Write vectored
|
|
||||||
file.write_vectored(slices.as_slice())
|
|
||||||
.map_err(AsyncIoError::WriteVectored)?
|
|
||||||
};
|
|
||||||
|
|
||||||
completion_list.push((user_data, result as i32));
|
|
||||||
eventfd.write(1).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fsync_sync(
|
|
||||||
user_data: Option<u64>,
|
|
||||||
file: &mut dyn Write,
|
|
||||||
eventfd: &EventFd,
|
|
||||||
completion_list: &mut Vec<(u64, i32)>,
|
|
||||||
semaphore: &mut Arc<Mutex<()>>,
|
|
||||||
) -> AsyncIoResult<()> {
|
|
||||||
let result: i32 = {
|
|
||||||
// Take the semaphore to ensure other threads are not interacting
|
|
||||||
// with the underlying file.
|
|
||||||
let _lock = semaphore.lock().unwrap();
|
|
||||||
|
|
||||||
// Flush
|
|
||||||
file.flush().map_err(AsyncIoError::Fsync)?;
|
|
||||||
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(user_data) = user_data {
|
|
||||||
completion_list.push((user_data, result));
|
|
||||||
eventfd.write(1).unwrap();
|
eventfd.write(1).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
fn write_vectored_sync(
|
||||||
|
&mut self,
|
||||||
|
offset: libc::off_t,
|
||||||
|
iovecs: Vec<libc::iovec>,
|
||||||
|
user_data: u64,
|
||||||
|
eventfd: &EventFd,
|
||||||
|
completion_list: &mut Vec<(u64, i32)>,
|
||||||
|
) -> AsyncIoResult<()> {
|
||||||
|
// Convert libc::iovec into IoSlice
|
||||||
|
let mut slices = Vec::new();
|
||||||
|
for iovec in iovecs.iter() {
|
||||||
|
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
let mut file = self.file();
|
||||||
|
|
||||||
|
// Move the cursor to the right offset
|
||||||
|
file.seek(SeekFrom::Start(offset as u64))
|
||||||
|
.map_err(AsyncIoError::WriteVectored)?;
|
||||||
|
|
||||||
|
// Write vectored
|
||||||
|
file.write_vectored(slices.as_slice())
|
||||||
|
.map_err(AsyncIoError::WriteVectored)?
|
||||||
|
};
|
||||||
|
|
||||||
|
completion_list.push((user_data, result as i32));
|
||||||
|
eventfd.write(1).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fsync_sync(
|
||||||
|
&mut self,
|
||||||
|
user_data: Option<u64>,
|
||||||
|
eventfd: &EventFd,
|
||||||
|
completion_list: &mut Vec<(u64, i32)>,
|
||||||
|
) -> AsyncIoResult<()> {
|
||||||
|
let result: i32 = {
|
||||||
|
let mut file = self.file();
|
||||||
|
|
||||||
|
// Flush
|
||||||
|
file.flush().map_err(AsyncIoError::Fsync)?;
|
||||||
|
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(user_data) = user_data {
|
||||||
|
completion_list.push((user_data, result));
|
||||||
|
eventfd.write(1).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file(&mut self) -> MutexGuard<F>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ImageType {
|
pub enum ImageType {
|
||||||
|
|||||||
@@ -2,59 +2,61 @@
|
|||||||
//
|
//
|
||||||
// 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, DiskFileResult};
|
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
|
||||||
use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync};
|
use crate::AsyncAdaptor;
|
||||||
use qcow::{QcowFile, RawFile, Result as QcowResult};
|
use qcow::{QcowFile, RawFile, Result as QcowResult};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::io::{Seek, SeekFrom};
|
||||||
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct QcowDiskSync {
|
pub struct QcowDiskSync {
|
||||||
qcow_file: QcowFile,
|
qcow_file: Arc<Mutex<QcowFile>>,
|
||||||
semaphore: Arc<Mutex<()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QcowDiskSync {
|
impl QcowDiskSync {
|
||||||
pub fn new(file: File, direct_io: bool) -> QcowResult<Self> {
|
pub fn new(file: File, direct_io: bool) -> QcowResult<Self> {
|
||||||
Ok(QcowDiskSync {
|
Ok(QcowDiskSync {
|
||||||
qcow_file: QcowFile::from(RawFile::new(file, direct_io))?,
|
qcow_file: Arc::new(Mutex::new(QcowFile::from(RawFile::new(file, direct_io))?)),
|
||||||
semaphore: Arc::new(Mutex::new(())),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskFile for QcowDiskSync {
|
impl DiskFile for QcowDiskSync {
|
||||||
fn size(&mut self) -> DiskFileResult<u64> {
|
fn size(&mut self) -> DiskFileResult<u64> {
|
||||||
disk_size(&mut self.qcow_file, &mut self.semaphore)
|
let mut file = self.qcow_file.lock().unwrap();
|
||||||
|
|
||||||
|
Ok(file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size)? as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
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(QcowSync::new(
|
Ok(Box::new(QcowSync::new(self.qcow_file.clone())) as Box<dyn AsyncIo>)
|
||||||
self.qcow_file.clone(),
|
|
||||||
self.semaphore.clone(),
|
|
||||||
)) as Box<dyn AsyncIo>)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QcowSync {
|
pub struct QcowSync {
|
||||||
qcow_file: QcowFile,
|
qcow_file: Arc<Mutex<QcowFile>>,
|
||||||
eventfd: EventFd,
|
eventfd: EventFd,
|
||||||
completion_list: Vec<(u64, i32)>,
|
completion_list: Vec<(u64, i32)>,
|
||||||
semaphore: Arc<Mutex<()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QcowSync {
|
impl QcowSync {
|
||||||
pub fn new(qcow_file: QcowFile, semaphore: Arc<Mutex<()>>) -> Self {
|
pub fn new(qcow_file: Arc<Mutex<QcowFile>>) -> Self {
|
||||||
QcowSync {
|
QcowSync {
|
||||||
qcow_file,
|
qcow_file,
|
||||||
eventfd: EventFd::new(libc::EFD_NONBLOCK)
|
eventfd: EventFd::new(libc::EFD_NONBLOCK)
|
||||||
.expect("Failed creating EventFd for QcowSync"),
|
.expect("Failed creating EventFd for QcowSync"),
|
||||||
completion_list: Vec::new(),
|
completion_list: Vec::new(),
|
||||||
semaphore,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsyncAdaptor<QcowFile> for Arc<Mutex<QcowFile>> {
|
||||||
|
fn file(&mut self) -> MutexGuard<QcowFile> {
|
||||||
|
self.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsyncIo for QcowSync {
|
impl AsyncIo for QcowSync {
|
||||||
fn notifier(&self) -> &EventFd {
|
fn notifier(&self) -> &EventFd {
|
||||||
&self.eventfd
|
&self.eventfd
|
||||||
@@ -66,14 +68,12 @@ impl AsyncIo for QcowSync {
|
|||||||
iovecs: Vec<libc::iovec>,
|
iovecs: Vec<libc::iovec>,
|
||||||
user_data: u64,
|
user_data: u64,
|
||||||
) -> AsyncIoResult<()> {
|
) -> AsyncIoResult<()> {
|
||||||
read_vectored_sync(
|
self.qcow_file.read_vectored_sync(
|
||||||
offset,
|
offset,
|
||||||
iovecs,
|
iovecs,
|
||||||
user_data,
|
user_data,
|
||||||
&mut self.qcow_file,
|
|
||||||
&self.eventfd,
|
&self.eventfd,
|
||||||
&mut self.completion_list,
|
&mut self.completion_list,
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,25 +83,18 @@ impl AsyncIo for QcowSync {
|
|||||||
iovecs: Vec<libc::iovec>,
|
iovecs: Vec<libc::iovec>,
|
||||||
user_data: u64,
|
user_data: u64,
|
||||||
) -> AsyncIoResult<()> {
|
) -> AsyncIoResult<()> {
|
||||||
write_vectored_sync(
|
self.qcow_file.write_vectored_sync(
|
||||||
offset,
|
offset,
|
||||||
iovecs,
|
iovecs,
|
||||||
user_data,
|
user_data,
|
||||||
&mut self.qcow_file,
|
|
||||||
&self.eventfd,
|
&self.eventfd,
|
||||||
&mut self.completion_list,
|
&mut self.completion_list,
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
||||||
fsync_sync(
|
self.qcow_file
|
||||||
user_data,
|
.fsync_sync(user_data, &self.eventfd, &mut self.completion_list)
|
||||||
&mut self.qcow_file,
|
|
||||||
&self.eventfd,
|
|
||||||
&mut self.completion_list,
|
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete(&mut self) -> Vec<(u64, i32)> {
|
fn complete(&mut self) -> Vec<(u64, i32)> {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, DiskTopology,
|
||||||
};
|
};
|
||||||
use io_uring::{opcode, squeue, types, IoUring};
|
use io_uring::{opcode, squeue, types, IoUring};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -35,6 +35,15 @@ impl DiskFile for RawFileDisk {
|
|||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
.map_err(DiskFileError::NewAsyncIo)?,
|
||||||
) as Box<dyn AsyncIo>)
|
) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn topology(&mut self) -> DiskTopology {
|
||||||
|
if let Ok(topology) = DiskTopology::probe(&mut self.file) {
|
||||||
|
topology
|
||||||
|
} else {
|
||||||
|
warn!("Unable to get device topology. Using default topology");
|
||||||
|
DiskTopology::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RawFileAsync {
|
pub struct RawFileAsync {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
|
|
||||||
use crate::async_io::{
|
use crate::async_io::{
|
||||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, DiskTopology,
|
||||||
};
|
};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
@@ -31,6 +31,15 @@ impl DiskFile for RawFileDiskSync {
|
|||||||
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(RawFileSync::new(self.file.as_raw_fd())) as Box<dyn AsyncIo>)
|
Ok(Box::new(RawFileSync::new(self.file.as_raw_fd())) as Box<dyn AsyncIo>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn topology(&mut self) -> DiskTopology {
|
||||||
|
if let Ok(topology) = DiskTopology::probe(&mut self.file) {
|
||||||
|
topology
|
||||||
|
} else {
|
||||||
|
warn!("Unable to get device topology. Using default topology");
|
||||||
|
DiskTopology::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RawFileSync {
|
pub struct RawFileSync {
|
||||||
|
|||||||
@@ -3,26 +3,20 @@
|
|||||||
// 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::{fsync_sync, read_vectored_sync, write_vectored_sync};
|
use crate::AsyncAdaptor;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::ops::DerefMut;
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use vhdx::vhdx::{Result as VhdxResult, Vhdx};
|
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 {
|
||||||
vhdx_file: Arc<Mutex<Vhdx>>,
|
vhdx_file: Arc<Mutex<Vhdx>>,
|
||||||
semaphore: Arc<Mutex<()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VhdxDiskSync {
|
impl VhdxDiskSync {
|
||||||
pub fn new(f: File) -> VhdxResult<Self> {
|
pub fn new(f: File) -> VhdxResult<Self> {
|
||||||
let vhdx = Vhdx::new(f)?;
|
|
||||||
let vhdx_file = Arc::new(Mutex::new(vhdx));
|
|
||||||
|
|
||||||
Ok(VhdxDiskSync {
|
Ok(VhdxDiskSync {
|
||||||
vhdx_file,
|
vhdx_file: Arc::new(Mutex::new(Vhdx::new(f)?)),
|
||||||
semaphore: Arc::new(Mutex::new(())),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,10 +27,10 @@ impl DiskFile for VhdxDiskSync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(
|
||||||
VhdxSync::new(self.vhdx_file.clone(), self.semaphore.clone())
|
Box::new(VhdxSync::new(self.vhdx_file.clone()).map_err(DiskFileError::NewAsyncIo)?)
|
||||||
.map_err(DiskFileError::NewAsyncIo)?,
|
as Box<dyn AsyncIo>,
|
||||||
) as Box<dyn AsyncIo>)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,20 +38,24 @@ pub struct VhdxSync {
|
|||||||
vhdx_file: Arc<Mutex<Vhdx>>,
|
vhdx_file: Arc<Mutex<Vhdx>>,
|
||||||
eventfd: EventFd,
|
eventfd: EventFd,
|
||||||
completion_list: Vec<(u64, i32)>,
|
completion_list: Vec<(u64, i32)>,
|
||||||
semaphore: Arc<Mutex<()>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VhdxSync {
|
impl VhdxSync {
|
||||||
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>, semaphore: Arc<Mutex<()>>) -> std::io::Result<Self> {
|
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>) -> std::io::Result<Self> {
|
||||||
Ok(VhdxSync {
|
Ok(VhdxSync {
|
||||||
vhdx_file,
|
vhdx_file,
|
||||||
eventfd: EventFd::new(libc::EFD_NONBLOCK)?,
|
eventfd: EventFd::new(libc::EFD_NONBLOCK)?,
|
||||||
completion_list: Vec::new(),
|
completion_list: Vec::new(),
|
||||||
semaphore,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsyncAdaptor<Vhdx> for Arc<Mutex<Vhdx>> {
|
||||||
|
fn file(&mut self) -> MutexGuard<Vhdx> {
|
||||||
|
self.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsyncIo for VhdxSync {
|
impl AsyncIo for VhdxSync {
|
||||||
fn notifier(&self) -> &EventFd {
|
fn notifier(&self) -> &EventFd {
|
||||||
&self.eventfd
|
&self.eventfd
|
||||||
@@ -69,14 +67,12 @@ impl AsyncIo for VhdxSync {
|
|||||||
iovecs: Vec<libc::iovec>,
|
iovecs: Vec<libc::iovec>,
|
||||||
user_data: u64,
|
user_data: u64,
|
||||||
) -> AsyncIoResult<()> {
|
) -> AsyncIoResult<()> {
|
||||||
read_vectored_sync(
|
self.vhdx_file.read_vectored_sync(
|
||||||
offset,
|
offset,
|
||||||
iovecs,
|
iovecs,
|
||||||
user_data,
|
user_data,
|
||||||
self.vhdx_file.lock().unwrap().deref_mut(),
|
|
||||||
&self.eventfd,
|
&self.eventfd,
|
||||||
&mut self.completion_list,
|
&mut self.completion_list,
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,25 +82,18 @@ impl AsyncIo for VhdxSync {
|
|||||||
iovecs: Vec<libc::iovec>,
|
iovecs: Vec<libc::iovec>,
|
||||||
user_data: u64,
|
user_data: u64,
|
||||||
) -> AsyncIoResult<()> {
|
) -> AsyncIoResult<()> {
|
||||||
write_vectored_sync(
|
self.vhdx_file.write_vectored_sync(
|
||||||
offset,
|
offset,
|
||||||
iovecs,
|
iovecs,
|
||||||
user_data,
|
user_data,
|
||||||
self.vhdx_file.lock().unwrap().deref_mut(),
|
|
||||||
&self.eventfd,
|
&self.eventfd,
|
||||||
&mut self.completion_list,
|
&mut self.completion_list,
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
||||||
fsync_sync(
|
self.vhdx_file
|
||||||
user_data,
|
.fsync_sync(user_data, &self.eventfd, &mut self.completion_list)
|
||||||
self.vhdx_file.lock().unwrap().deref_mut(),
|
|
||||||
&self.eventfd,
|
|
||||||
&mut self.completion_list,
|
|
||||||
&mut self.semaphore,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete(&mut self) -> Vec<(u64, i32)> {
|
fn complete(&mut self) -> Vec<(u64, i32)> {
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables", optional = true }
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.52"
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
bitflags = "1.3.2"
|
bitflags = "1.3.2"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.6.0"
|
vm-memory = "0.7.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ impl BusDevice for AcpiGedDevice {
|
|||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
impl Aml for AcpiGedDevice {
|
impl Aml for AcpiGedDevice {
|
||||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||||
aml::Device::new(
|
aml::Device::new(
|
||||||
"_SB_.GED_".into(),
|
"_SB_.GED_".into(),
|
||||||
vec![
|
vec![
|
||||||
@@ -151,7 +151,7 @@ impl Aml for AcpiGedDevice {
|
|||||||
&aml::And::new(&aml::Local(1), &aml::Local(0), &4usize),
|
&aml::And::new(&aml::Local(1), &aml::Local(0), &4usize),
|
||||||
&aml::If::new(
|
&aml::If::new(
|
||||||
&aml::Equal::new(&aml::Local(1), &4usize),
|
&aml::Equal::new(&aml::Local(1), &4usize),
|
||||||
vec![&aml::MethodCall::new("\\_SB_.PCI0.PCNT".into(), vec![])],
|
vec![&aml::MethodCall::new("\\_SB_.PHPR.PSCN".into(), vec![])],
|
||||||
),
|
),
|
||||||
&aml::And::new(&aml::Local(1), &aml::Local(0), &8usize),
|
&aml::And::new(&aml::Local(1), &aml::Local(0), &8usize),
|
||||||
&aml::If::new(
|
&aml::If::new(
|
||||||
@@ -165,7 +165,7 @@ impl Aml for AcpiGedDevice {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.to_aml_bytes()
|
.append_aml_bytes(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ impl BusDevice for Cmos {
|
|||||||
0x09 => to_bcd((year % 100) as u8),
|
0x09 => to_bcd((year % 100) as u8),
|
||||||
// Bit 5 for 32kHz clock. Bit 7 for Update in Progress
|
// Bit 5 for 32kHz clock. Bit 7 for Update in Progress
|
||||||
0x0a => 1 << 5 | (update_in_progress as u8) << 7,
|
0x0a => 1 << 5 | (update_in_progress as u8) << 7,
|
||||||
|
// Bit 0-6 are reserved and must be 0.
|
||||||
|
// Bit 7 must be 1 (CMOS has power)
|
||||||
|
0x0d => 1 << 7,
|
||||||
0x32 => to_bcd(((year + 1900) / 100) as u8),
|
0x32 => to_bcd(((year + 1900) / 100) as u8),
|
||||||
_ => {
|
_ => {
|
||||||
// self.index is always guaranteed to be in range via INDEX_MASK.
|
// self.index is always guaranteed to be in range via INDEX_MASK.
|
||||||
|
|||||||
@@ -291,14 +291,13 @@ impl Rtc {
|
|||||||
|
|
||||||
impl BusDevice for Rtc {
|
impl BusDevice for Rtc {
|
||||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||||
let v;
|
|
||||||
let mut read_ok = true;
|
let mut read_ok = true;
|
||||||
|
|
||||||
if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&offset) {
|
let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&offset) {
|
||||||
let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
|
let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
|
||||||
v = u32::from(PL031_ID[index]);
|
u32::from(PL031_ID[index])
|
||||||
} else {
|
} else {
|
||||||
v = match offset {
|
match offset {
|
||||||
RTCDR => self.get_time(),
|
RTCDR => self.get_time(),
|
||||||
RTCMR => {
|
RTCMR => {
|
||||||
// Even though we are not implementing RTC alarm we return the last value
|
// Even though we are not implementing RTC alarm we return the last value
|
||||||
@@ -313,8 +312,8 @@ impl BusDevice for Rtc {
|
|||||||
read_ok = false;
|
read_ok = false;
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
if read_ok && data.len() <= 4 {
|
if read_ok && data.len() <= 4 {
|
||||||
write_le_u32(data, v);
|
write_le_u32(data, v);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -294,19 +294,15 @@ impl Pl011 {
|
|||||||
|
|
||||||
impl BusDevice for Pl011 {
|
impl BusDevice for Pl011 {
|
||||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||||
let v;
|
|
||||||
let mut read_ok = true;
|
let mut read_ok = true;
|
||||||
if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) {
|
let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&(offset >> 2)) {
|
||||||
let index = ((offset - 0xfe0) >> 2) as usize;
|
let index = ((offset - 0xfe0) >> 2) as usize;
|
||||||
v = u32::from(PL011_ID[index]);
|
u32::from(PL011_ID[index])
|
||||||
} else {
|
} else {
|
||||||
v = match offset >> 2 {
|
match offset >> 2 {
|
||||||
UARTDR => {
|
UARTDR => {
|
||||||
let c: u32;
|
|
||||||
let r: u32;
|
|
||||||
|
|
||||||
self.flags &= !PL011_FLAG_RXFF;
|
self.flags &= !PL011_FLAG_RXFF;
|
||||||
c = self.read_fifo.pop_front().unwrap_or_default().into();
|
let c: u32 = self.read_fifo.pop_front().unwrap_or_default().into();
|
||||||
if self.read_count > 0 {
|
if self.read_count > 0 {
|
||||||
self.read_count -= 1;
|
self.read_count -= 1;
|
||||||
}
|
}
|
||||||
@@ -317,8 +313,7 @@ impl BusDevice for Pl011 {
|
|||||||
self.int_level &= !PL011_INT_RX;
|
self.int_level &= !PL011_INT_RX;
|
||||||
}
|
}
|
||||||
self.rsr = c >> 8;
|
self.rsr = c >> 8;
|
||||||
r = c;
|
c
|
||||||
r
|
|
||||||
}
|
}
|
||||||
UARTRSR_UARTECR => self.rsr,
|
UARTRSR_UARTECR => self.rsr,
|
||||||
UARTFR => self.flags,
|
UARTFR => self.flags,
|
||||||
@@ -337,7 +332,7 @@ impl BusDevice for Pl011 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if read_ok && data.len() <= 4 {
|
if read_ok && data.len() <= 4 {
|
||||||
write_le_u32(data, v);
|
write_le_u32(data, v);
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
# How to build and test Cloud Hypervisor on AArch64
|
# How to build and test Cloud Hypervisor on AArch64
|
||||||
|
|
||||||
This document introduces how to build and test Cloud Hypervisor on AArch64 servers. Currently Cloud Hypervisor cannot be tested on Raspberry PI. Because on AArch64, Cloud Hypervisor requires GICv3-ITS device for PCIe MSI interrupt handling. But GICv3-ITS has not been equipped on any Raspberry PI product so far.
|
This document introduces how to build and test Cloud Hypervisor on AArch64.
|
||||||
|
Currently, Cloud Hypervisor supports 2 methods of booting on AArch64: UEFI
|
||||||
|
booting and direct-kernel booting. The document covers both methods.
|
||||||
|
|
||||||
Now Cloud Hypervisor supports 2 ways of booting on AArch64: UEFI booting and direct-kernel booting. The document covers both of the ways.
|
All the steps are based on Ubuntu. We use the Ubuntu cloud image for guest VM
|
||||||
|
disk.
|
||||||
|
|
||||||
All the steps are based on Ubuntu. We use the Ubuntu cloud image for guest VM disk.
|
## Hardware requirements
|
||||||
|
|
||||||
|
- AArch64 servers (recommended) or development boards equipped with the GICv3
|
||||||
|
interrupt controller.
|
||||||
|
|
||||||
|
- On development boards that have constrained RAM resources, if the creation of
|
||||||
|
a VM consumes a large portion of the free memory on the host, it may be required
|
||||||
|
to enable swap. For example, this was required on a board with 3 GB of RAM
|
||||||
|
booting a 2 GB VM at a point in time when 2.8 GB were free. Without enabling
|
||||||
|
swap the `cloud-hypervisor` process was terminated by the OOM killer. In this
|
||||||
|
situation memory was allocated for the virtual machine using memfd while the
|
||||||
|
page cache was filled, leading to a situation where the kernel could not even
|
||||||
|
drop caches. Making a small section of swap available (observably, 1 to 15 MB),
|
||||||
|
this situation can be resolved and the resulting memory footprint of
|
||||||
|
`cloud-hypervisor` is as expected.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
@@ -82,19 +99,29 @@ $ build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtCloudHv.dsc -b RELEASE
|
|||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
If the build goes well, the EDK2 binary is available at `edk2/Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd`.
|
If the build goes well, the EDK2 binary is available at
|
||||||
|
`edk2/Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd`.
|
||||||
|
|
||||||
### Booting the guest VM
|
### Booting the guest VM
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ pushd $CLOUDH
|
$ pushd $CLOUDH
|
||||||
$ sudo RUST_BACKTRACE=1 $CLOUDH/cloud-hypervisor/target/debug/cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock --kernel $CLOUDH/edk2/edk2/Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd --disk path=$CLOUDH/focal-server-cloudimg-arm64.raw --cpus boot=4 --memory size=4096M --serial tty --console off --log-file log.log -vvv --net tap=,mac=12:34:56:78:90:01,ip=192.168.1.1,mask=255.255.255.0
|
$ sudo RUST_BACKTRACE=1 $CLOUDH/cloud-hypervisor/target/debug/cloud-hypervisor \
|
||||||
|
--api-socket /tmp/cloud-hypervisor.sock \
|
||||||
|
--kernel $CLOUDH/edk2/Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd \
|
||||||
|
--disk path=$CLOUDH/focal-server-cloudimg-arm64.raw \
|
||||||
|
--cpus boot=4 \
|
||||||
|
--memory size=4096M \
|
||||||
|
--net tap=,mac=12:34:56:78:90:01,ip=192.168.1.1,mask=255.255.255.0 \
|
||||||
|
--serial tty \
|
||||||
|
--console off
|
||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|
||||||
## Direct-kernel booting
|
## Direct-kernel booting
|
||||||
|
|
||||||
Alternativelly, you can build your own kernel for guest VM. This way, UEFI is not involved and ACPI cannot be enabled.
|
Alternativelly, you can build your own kernel for guest VM. This way, UEFI is
|
||||||
|
not involved and ACPI cannot be enabled.
|
||||||
|
|
||||||
### Building kernel
|
### Building kernel
|
||||||
|
|
||||||
@@ -111,6 +138,15 @@ $ popd
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ pushd $CLOUDH
|
$ pushd $CLOUDH
|
||||||
$ sudo $CLOUDH/cloud-hypervisor/target/debug/cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock --kernel $CLOUDH/linux/arch/arm64/boot/Image --disk path=focal-server-cloudimg-arm64.raw --cmdline "keep_bootcon console=ttyAMA0 reboot=k panic=1 root=/dev/vda1 rw" --cpus boot=4 --memory size=4096M --serial tty --console off --log-file log.log -vvv --net "tap=,mac=,ip=,mask="
|
$ sudo $CLOUDH/cloud-hypervisor/target/debug/cloud-hypervisor \
|
||||||
|
--api-socket /tmp/cloud-hypervisor.sock \
|
||||||
|
--kernel $CLOUDH/linux/arch/arm64/boot/Image \
|
||||||
|
--disk path=focal-server-cloudimg-arm64.raw \
|
||||||
|
--cmdline "keep_bootcon console=ttyAMA0 reboot=k panic=1 root=/dev/vda1 rw" \
|
||||||
|
--cpus boot=4 \
|
||||||
|
--memory size=4096M \
|
||||||
|
--net tap=,mac=12:34:56:78:90:01,ip=192.168.1.1,mask=255.255.255.0 \
|
||||||
|
--serial tty \
|
||||||
|
--console off
|
||||||
$ popd
|
$ popd
|
||||||
```
|
```
|
||||||
|
|||||||
189
docs/cpu.md
Normal file
189
docs/cpu.md
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
# CPU
|
||||||
|
|
||||||
|
Cloud Hypervisor has many options when it comes to the creation of virtual
|
||||||
|
CPUs. This document aims to explain what Cloud Hypervisor is capable of and
|
||||||
|
how it can be used to meet the needs of very different use cases.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
`CpusConfig` or what is known as `--cpus` from the CLI perspective is the way
|
||||||
|
to set vCPUs options for Cloud Hypervisor.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct CpusConfig {
|
||||||
|
boot_vcpus: u8,
|
||||||
|
max_vcpus: u8,
|
||||||
|
topology: Option<CpuTopology>,
|
||||||
|
kvm_hyperv: bool,
|
||||||
|
max_phys_bits: u8,
|
||||||
|
affinity: Option<Vec<CpuAffinity>>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>
|
||||||
|
```
|
||||||
|
|
||||||
|
### `boot`
|
||||||
|
|
||||||
|
Number of vCPUs present at boot time.
|
||||||
|
|
||||||
|
This option allows to define a specific number of vCPUs to be present at the
|
||||||
|
time the VM is started. This option is mandatory when using the `--cpus`
|
||||||
|
parameter. If `--cpus` is not specified, this option takes the default value
|
||||||
|
of `1`, starting the VM with a single vCPU.
|
||||||
|
|
||||||
|
Value is an unsigned integer of 8 bits.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus boot=2
|
||||||
|
```
|
||||||
|
|
||||||
|
### `max`
|
||||||
|
|
||||||
|
Maximum number of vCPUs.
|
||||||
|
|
||||||
|
This option defines the maximum number of vCPUs that can be assigned to the VM.
|
||||||
|
In particular, this option is used when looking for CPU hotplug as it lets the
|
||||||
|
provide an indication about how many vCPUs might be needed later during the
|
||||||
|
runtime of the VM.
|
||||||
|
For instance, if booting the VM with 2 vCPUs and a maximum of 6 vCPUs, it means
|
||||||
|
up to 4 vCPUs can be added later at runtime by resizing the VM.
|
||||||
|
|
||||||
|
The value must be greater than or equal to the number of boot vCPUs.
|
||||||
|
The value is an unsigned integer of 8 bits.
|
||||||
|
|
||||||
|
By default this option takes the value of `boot`, meaning vCPU hotplug is not
|
||||||
|
expected and can't be performed.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus max=3
|
||||||
|
```
|
||||||
|
|
||||||
|
### `topology`
|
||||||
|
|
||||||
|
Topology of the guest platform.
|
||||||
|
|
||||||
|
This option gives the user a way to describe the exact topology that should be
|
||||||
|
exposed to the guest. It can be useful to describe to the guest the same
|
||||||
|
topology found on the host as it allows for proper usage of the resources and
|
||||||
|
is a way to achieve better performances.
|
||||||
|
|
||||||
|
The topology is described through the following structure:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct CpuTopology {
|
||||||
|
threads_per_core: u8,
|
||||||
|
cores_per_die: u8,
|
||||||
|
dies_per_package: u8,
|
||||||
|
packages: u8,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
or the following syntax through the CLI:
|
||||||
|
|
||||||
|
```
|
||||||
|
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>
|
||||||
|
```
|
||||||
|
|
||||||
|
By default the topology will be `1:1:1:1`.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus boot=2,topology=1:1:2:1
|
||||||
|
```
|
||||||
|
|
||||||
|
### `kvm_hyperv`
|
||||||
|
|
||||||
|
Enable KVM Hyper-V emulation.
|
||||||
|
|
||||||
|
When turned on, this option relies on KVM to emulate the synthetic interrupt
|
||||||
|
controller (SynIC) along with synthetic timers expected by a Windows guest.
|
||||||
|
A Windows guest usually runs on top of Microsoft Hyper-V, therefore expects
|
||||||
|
these synthetic devices to be present. That's why KVM provides a way to emulate
|
||||||
|
them and avoids failures running a Windows guest with Cloud Hypervisor.
|
||||||
|
|
||||||
|
By default this option is turned off.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus kvm_hyperv=on
|
||||||
|
```
|
||||||
|
|
||||||
|
### `max_phys_bits`
|
||||||
|
|
||||||
|
Maximum size for guest's addressable space.
|
||||||
|
|
||||||
|
This option defines the maximum number of physical bits for all vCPUs, which
|
||||||
|
sets a limit for the size of the guest's addressable space. This is mainly
|
||||||
|
useful for debug purpose.
|
||||||
|
|
||||||
|
The value is an unsigned integer of 8 bits.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus max_phys_bits=40
|
||||||
|
```
|
||||||
|
|
||||||
|
### `affinity`
|
||||||
|
|
||||||
|
Affinity of each vCPU.
|
||||||
|
|
||||||
|
This option gives the user a way to provide the host CPU set associated with
|
||||||
|
each vCPU. It is useful for achieving CPU pinning, ensuring multiple VMs won't
|
||||||
|
affect the performance of each other. It might also be used in the context of
|
||||||
|
NUMA as it is way of making sure the VM can run on a specific host NUMA node.
|
||||||
|
In general, this option is used to increase the performances of a VM depending
|
||||||
|
on the host platform and the type of workload running in the guest.
|
||||||
|
|
||||||
|
The affinity is described through the following structure:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct CpuAffinity {
|
||||||
|
vcpu: u8,
|
||||||
|
host_cpus: Vec<u8>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
or the following syntax through the CLI:
|
||||||
|
|
||||||
|
```
|
||||||
|
affinity=[<vcpu_id1>@[<host_cpu_id1>, <host_cpu_id2>], <vcpu_id2>@[<host_cpu_id3>, <host_cpu_id4>]]
|
||||||
|
```
|
||||||
|
|
||||||
|
The outer brackets define the list of vCPUs. And for each vCPU, the inner
|
||||||
|
brackets attached to `@` define the list of host CPUs the vCPU is allowed to
|
||||||
|
run onto.
|
||||||
|
|
||||||
|
Multiple values can be provided to define each list. Each value is an unsigned
|
||||||
|
integer of 8 bits.
|
||||||
|
|
||||||
|
For instance, if one needs to run vCPU 0 on host CPUs from 0 to 4, the syntax
|
||||||
|
using `-` will help define a contiguous range with `affinity=0@[0-4]`. The
|
||||||
|
same example could also be described with `affinity=0@[0,1,2,3,4]`.
|
||||||
|
|
||||||
|
A combination of both `-` and `,` separators is useful when one might need to
|
||||||
|
describe a list containing host CPUs from 0 to 99 and the host CPU 255, as it
|
||||||
|
could simply be described with `affinity=0@[0-99,255]`.
|
||||||
|
|
||||||
|
As soon as one tries to describe a list of values, `[` and `]` must be used to
|
||||||
|
demarcate the list.
|
||||||
|
|
||||||
|
By default each vCPU runs on the entire host CPU set.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--cpus boot=3,affinity=[0@[2,3],1@[0,1]]
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, assuming the host has 4 CPUs, vCPU 0 will run exclusively on
|
||||||
|
host CPUs 2 and 3, while vCPU 1 will run exclusively on host CPUs 0 and 1.
|
||||||
|
Because nothing is defined for vCPU 2, it can run on any of the 4 host CPUs.
|
||||||
@@ -72,7 +72,7 @@ mount -t devpts devpts /dev/pts
|
|||||||
|
|
||||||
### Install needed packages
|
### Install needed packages
|
||||||
|
|
||||||
In the context Cloud-Hypervisor's integration tests, we need several utilities.
|
In the context Cloud Hypervisor's integration tests, we need several utilities.
|
||||||
Here is the way to install them for a Ubuntu image. This step is specific to
|
Here is the way to install them for a Ubuntu image. This step is specific to
|
||||||
Ubuntu distributions.
|
Ubuntu distributions.
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ feature is enabled by default.
|
|||||||
## Virtio devices
|
## Virtio devices
|
||||||
|
|
||||||
For all virtio devices listed below, only `virtio-pci` transport layer is
|
For all virtio devices listed below, only `virtio-pci` transport layer is
|
||||||
supported.
|
supported. Cloud Hypervisor supports multiple PCI segments, and users can
|
||||||
|
append `,pci_segment=<PCI_segment_number>` to the device flag in the Cloud
|
||||||
|
Hypervisor command line to assign devices to a specific PCI segment.
|
||||||
|
|
||||||
### virtio-block
|
### virtio-block
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Cloud Hypervisor Hot Plug
|
# Cloud Hypervisor Hot Plug
|
||||||
|
|
||||||
Currently Cloud Hypervisor only support hot plugging of CPU devices.
|
Currently Cloud Hypervisor supports hot plugging of CPUs devices (x86 only), PCI devices and memory resizing.
|
||||||
|
|
||||||
## Kernel support
|
## Kernel support
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ or by using this kernel patch (available in 5.5-rc1 and later): https://git.kern
|
|||||||
|
|
||||||
## CPU Hot Plug
|
## CPU Hot Plug
|
||||||
|
|
||||||
Extra vCPUs can be added and removed from a running Cloud Hypervisor instance. This is controlled by two mechanisms:
|
Extra vCPUs can be added and removed from a running `cloud-hypervisor` instance. This is controlled by two mechanisms:
|
||||||
|
|
||||||
1. Specifying a number of maximum potential vCPUs that is greater than the number of default (boot) vCPUs.
|
1. Specifying a number of maximum potential vCPUs that is greater than the number of default (boot) vCPUs.
|
||||||
2. Making a HTTP API request to the VMM to ask for the additional vCPUs to be added.
|
2. Making a HTTP API request to the VMM to ask for the additional vCPUs to be added.
|
||||||
@@ -65,7 +65,7 @@ As per adding CPUs to the guest, after a reboot the VM will be running with the
|
|||||||
|
|
||||||
### ACPI method
|
### ACPI method
|
||||||
|
|
||||||
Extra memory can be added from a running Cloud Hypervisor instance. This is controlled by two mechanisms:
|
Extra memory can be added from a running `cloud-hypervisor` instance. This is controlled by two mechanisms:
|
||||||
|
|
||||||
1. Allocating some of the guest physical address space for hotplug memory.
|
1. Allocating some of the guest physical address space for hotplug memory.
|
||||||
2. Making a HTTP API request to the VMM to ask for a new amount of RAM to be assigned to the VM. In the case of expanding the memory for the VM the new memory will be hotplugged into the running VM, if reducing the size of the memory then change will take effect after the next reboot.
|
2. Making a HTTP API request to the VMM to ask for a new amount of RAM to be assigned to the VM. In the case of expanding the memory for the VM the new memory will be hotplugged into the running VM, if reducing the size of the memory then change will take effect after the next reboot.
|
||||||
@@ -157,7 +157,7 @@ The same API can also be used to reduce the desired RAM for a VM. It is importan
|
|||||||
|
|
||||||
## PCI Device Hot Plug
|
## PCI Device Hot Plug
|
||||||
|
|
||||||
Extra PCI devices can be added and removed from a running Cloud Hypervisor instance. This is controlled by making a HTTP API request to the VMM to ask for the additional device to be added, or for the existing device to be removed.
|
Extra PCI devices can be added and removed from a running `cloud-hypervisor` instance. This is controlled by making a HTTP API request to the VMM to ask for the additional device to be added, or for the existing device to be removed.
|
||||||
|
|
||||||
Note: On AArch64 platform, PCI device hotplug can only be achieved using ACPI. Please refer to the [documentation](arm64.md#uefi-booting) for more information.
|
Note: On AArch64 platform, PCI device hotplug can only be achieved using ACPI. Please refer to the [documentation](arm64.md#uefi-booting) for more information.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Intel SGX
|
# Intel SGX
|
||||||
|
|
||||||
Intel® Software Guard Extensions (Intel® SGX) is an Intel technology designed
|
Intel® Software Guard Extensions (Intel® SGX) is an Intel technology designed
|
||||||
to increase the security of application code and data. Cloud-Hypervisor supports
|
to increase the security of application code and data. Cloud Hypervisor supports
|
||||||
SGX virtualization through KVM. Because SGX is built on hardware features that
|
SGX virtualization through KVM. Because SGX is built on hardware features that
|
||||||
cannot be emulated in software, virtualizing SGX requires support in KVM and in
|
cannot be emulated in software, virtualizing SGX requires support in KVM and in
|
||||||
the host kernel. The required Linux and KVM changes can be found in the
|
the host kernel. The required Linux and KVM changes can be found in the
|
||||||
@@ -17,12 +17,12 @@ For more information about SGX, please refer to the [SGX Homepage](https://softw
|
|||||||
For more information about SGX SDK and how to test SGX, please refer to the
|
For more information about SGX SDK and how to test SGX, please refer to the
|
||||||
following [instructions](https://github.com/intel/linux-sgx).
|
following [instructions](https://github.com/intel/linux-sgx).
|
||||||
|
|
||||||
## Cloud-Hypervisor support
|
## Cloud Hypervisor support
|
||||||
|
|
||||||
Assuming the host exposes `/dev/sgx_vepc`, we can pass SGX enclaves through
|
Assuming the host exposes `/dev/sgx_vepc`, we can pass SGX enclaves through
|
||||||
the guest.
|
the guest.
|
||||||
|
|
||||||
In order to use SGX enclaves within a Cloud-Hypervisor VM, we must define one
|
In order to use SGX enclaves within a Cloud Hypervisor VM, we must define one
|
||||||
or several Enclave Page Cache (EPC) sections. Here is an example of a VM being
|
or several Enclave Page Cache (EPC) sections. Here is an example of a VM being
|
||||||
created with 2 EPC sections, the first one being 64MiB with pre-allocated
|
created with 2 EPC sections, the first one being 64MiB with pre-allocated
|
||||||
memory, the second one being 32MiB with no pre-allocated memory.
|
memory, the second one being 32MiB with no pre-allocated memory.
|
||||||
|
|||||||
75
docs/intel_tdx.md
Normal file
75
docs/intel_tdx.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# Intel TDX
|
||||||
|
|
||||||
|
Intel® Trust Domain Extensions (Intel® TDX) is an Intel technology designed to
|
||||||
|
isolate virtual machines from the VMM, hypervisor and any other software on the
|
||||||
|
host platform.
|
||||||
|
|
||||||
|
For more information about TDX technical aspects, design and specification
|
||||||
|
please refer to the
|
||||||
|
[TDX Homepage](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html).
|
||||||
|
|
||||||
|
The required Linux changes for the host side can be found in the
|
||||||
|
[KVM TDX tree](https://github.com/intel/tdx/tree/kvm) while the changes for
|
||||||
|
the guest side can be found in the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
|
||||||
|
|
||||||
|
The TDVF firmware can be found in the
|
||||||
|
[EDK2 staging project](https://github.com/tianocore/edk2-staging/tree/TDVF).
|
||||||
|
|
||||||
|
## Cloud Hypervisor support
|
||||||
|
|
||||||
|
First, you must be running on a machine with TDX enabled in hardware, and
|
||||||
|
with the host OS compiled from the [KVM TDX tree](https://github.com/intel/tdx/tree/kvm).
|
||||||
|
|
||||||
|
Cloud Hypervisor can run TDX VM (Trust Domain) by loading the TDVF firmware,
|
||||||
|
which will then load the guest kernel from the image. The image must be custom
|
||||||
|
as it must include a kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
|
||||||
|
The firmware can be built as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/tianocore/edk2-staging.git
|
||||||
|
cd edk2-staging
|
||||||
|
git checkout origin/TDVF
|
||||||
|
git submodule update --init --recursive
|
||||||
|
make -C BaseTools
|
||||||
|
source ./edksetup.sh
|
||||||
|
build -p OvmfPkg/OvmfCh.dsc -a X64 -t GCC5 -b RELEASE
|
||||||
|
```
|
||||||
|
|
||||||
|
If debug logs are needed, here is the alternative command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
build -p OvmfPkg/OvmfCh.dsc -a X64 -t GCC5 -D DEBUG_ON_SERIAL_PORT=TRUE
|
||||||
|
```
|
||||||
|
|
||||||
|
On the Cloud Hypervisor side, all you need is to build the project with the
|
||||||
|
`tdx` feature enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --features tdx
|
||||||
|
```
|
||||||
|
|
||||||
|
And run a TDX VM by providing the firmware previously built, along with the
|
||||||
|
guest image containing the TDX enlightened kernel. Assuming the guest kernel
|
||||||
|
command line contains `console=hvc0` (printing to the `virtio-console` device),
|
||||||
|
run Cloud Hypervisor as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./cloud-hypervisor \
|
||||||
|
--tdx firmware=edk2-staging/Build/OvmfCh/RELEASE_GCC5/FV/OVMF.fd \
|
||||||
|
--cpus boot=1 \
|
||||||
|
--memory size=1G \
|
||||||
|
--disk path=tdx_guest_img
|
||||||
|
```
|
||||||
|
|
||||||
|
And here is the alternative command when looking for debug logs (assuming the
|
||||||
|
guest kernel command line contains `console=ttyS0`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./cloud-hypervisor \
|
||||||
|
--tdx firmware=edk2-staging/Build/OvmfCh/DEBUG_GCC5/FV/OVMF.fd \
|
||||||
|
--cpus boot=1 \
|
||||||
|
--memory size=1G \
|
||||||
|
--disk path=tdx_guest_img \
|
||||||
|
--serial tty \
|
||||||
|
--console off
|
||||||
|
```
|
||||||
@@ -8,13 +8,13 @@ support in Cloud Hypervisor:
|
|||||||
1. nested-vm migration - migrating between two nested VMs whose host VMs
|
1. nested-vm migration - migrating between two nested VMs whose host VMs
|
||||||
are running on the same machine.
|
are running on the same machine.
|
||||||
|
|
||||||
## Local Migration
|
## Local Migration (Suitable for Live Upgrade of VMM)
|
||||||
Launch the source VM (on the host machine):
|
Launch the source VM (on the host machine):
|
||||||
```bash
|
```bash
|
||||||
$ target/release/cloud-hypervisor
|
$ target/release/cloud-hypervisor
|
||||||
--kernel ~/workloads/vmlinux \
|
--kernel ~/workloads/vmlinux \
|
||||||
--disk path=~/workloads/focal.raw \
|
--disk path=~/workloads/focal.raw \
|
||||||
--cpus boot=1 --memory size=1G \
|
--cpus boot=1 --memory size=1G,shared=on \
|
||||||
--cmdline "root=/dev/vda1 console=ttyS0" \
|
--cmdline "root=/dev/vda1 console=ttyS0" \
|
||||||
--serial tty --console off --api-socket=/tmp/api1
|
--serial tty --console off --api-socket=/tmp/api1
|
||||||
```
|
```
|
||||||
@@ -31,7 +31,7 @@ $ target/release/ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/so
|
|||||||
|
|
||||||
Start to send migration for the source VM (on the host machine):
|
Start to send migration for the source VM (on the host machine):
|
||||||
```bash
|
```bash
|
||||||
$ target/release/ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/sock
|
$ target/release/ch-remote --api-socket=/tmp/api1 send-migration --local unix:/tmp/sock
|
||||||
```
|
```
|
||||||
|
|
||||||
When the above commands completed, the source VM should be successfully
|
When the above commands completed, the source VM should be successfully
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Memory
|
# Memory
|
||||||
|
|
||||||
Cloud-Hypervisor has many ways to expose memory to the guest VM. This document
|
Cloud Hypervisor has many ways to expose memory to the guest VM. This document
|
||||||
aims to explain what Cloud-Hypervisor is capable of and how it can be used to
|
aims to explain what Cloud Hypervisor is capable of and how it can be used to
|
||||||
meet the needs of very different use cases.
|
meet the needs of very different use cases.
|
||||||
|
|
||||||
## Basic Parameters
|
## Basic Parameters
|
||||||
|
|
||||||
`MemoryConfig` or what is known as `--memory` from the CLI perspective is the
|
`MemoryConfig` or what is known as `--memory` from the CLI perspective is the
|
||||||
easiest way to get started with Cloud-Hypervisor.
|
easiest way to get started with Cloud Hypervisor.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct MemoryConfig {
|
struct MemoryConfig {
|
||||||
@@ -446,17 +446,20 @@ integer of 8 bits.
|
|||||||
|
|
||||||
For instance, if one needs to attach all CPUs from 0 to 4 to a specific node,
|
For instance, if one needs to attach all CPUs from 0 to 4 to a specific node,
|
||||||
the syntax using `-` will help define a contiguous range with `cpus=0-4`. The
|
the syntax using `-` will help define a contiguous range with `cpus=0-4`. The
|
||||||
same example could also be described with `cpus=0:1:2:3:4`.
|
same example could also be described with `cpus=[0,1,2,3,4]`.
|
||||||
|
|
||||||
A combination of both `-` and `:` separators is useful when one might need to
|
A combination of both `-` and `,` separators is useful when one might need to
|
||||||
describe a list containing all CPUs from 0 to 99 and the CPU 255, as it could
|
describe a list containing all CPUs from 0 to 99 and the CPU 255, as it could
|
||||||
simply be described with `cpus=0-99:255`.
|
simply be described with `cpus=[0-99,255]`.
|
||||||
|
|
||||||
|
As soon as one tries to describe a list of values, `[` and `]` must be used to
|
||||||
|
demarcate the list.
|
||||||
|
|
||||||
_Example_
|
_Example_
|
||||||
|
|
||||||
```
|
```
|
||||||
--cpus boot=8
|
--cpus boot=8
|
||||||
--numa guest_numa_id=0,cpus=1-3:7 guest_numa_id=1,cpus=0:4-6
|
--numa guest_numa_id=0,cpus=[1-3,7] guest_numa_id=1,cpus=[0,4-6]
|
||||||
```
|
```
|
||||||
|
|
||||||
### `distances`
|
### `distances`
|
||||||
@@ -473,7 +476,10 @@ node. The second value is an unsigned integer of 8 bits as it represents the
|
|||||||
distance between the current NUMA node and the destination NUMA node. The two
|
distance between the current NUMA node and the destination NUMA node. The two
|
||||||
values are separated by `@` (`value1@value2`), meaning the destination NUMA
|
values are separated by `@` (`value1@value2`), meaning the destination NUMA
|
||||||
node `value1` is located at a distance of `value2`. Each tuple is separated
|
node `value1` is located at a distance of `value2`. Each tuple is separated
|
||||||
from the others with `:` separator.
|
from the others with `,` separator.
|
||||||
|
|
||||||
|
As soon as one tries to describe a list of values, `[` and `]` must be used to
|
||||||
|
demarcate the list.
|
||||||
|
|
||||||
For instance, if one wants to define 3 NUMA nodes, with each node located at
|
For instance, if one wants to define 3 NUMA nodes, with each node located at
|
||||||
different distances, it can be described with the following example.
|
different distances, it can be described with the following example.
|
||||||
@@ -481,7 +487,7 @@ different distances, it can be described with the following example.
|
|||||||
_Example_
|
_Example_
|
||||||
|
|
||||||
```
|
```
|
||||||
--numa guest_numa_id=0,distances=1@15:2@25 guest_numa_id=1,distances=0@15:2@20 guest_numa_id=2,distances=0@25:1@20
|
--numa guest_numa_id=0,distances=[1@15,2@25] guest_numa_id=1,distances=[0@15,2@20] guest_numa_id=2,distances=[0@25,1@20]
|
||||||
```
|
```
|
||||||
|
|
||||||
### `memory_zones`
|
### `memory_zones`
|
||||||
@@ -498,7 +504,10 @@ workload run more efficiently.
|
|||||||
|
|
||||||
Multiple values can be provided to define the list. Each value is a string
|
Multiple values can be provided to define the list. Each value is a string
|
||||||
referring to an existing memory zone identifier. Values are separated from
|
referring to an existing memory zone identifier. Values are separated from
|
||||||
each other with the `:` separator.
|
each other with the `,` separator.
|
||||||
|
|
||||||
|
As soon as one tries to describe a list of values, `[` and `]` must be used to
|
||||||
|
demarcate the list.
|
||||||
|
|
||||||
Note that a memory zone must belong to a single NUMA node. The following
|
Note that a memory zone must belong to a single NUMA node. The following
|
||||||
configuration is incorrect, therefore not allowed:
|
configuration is incorrect, therefore not allowed:
|
||||||
@@ -509,7 +518,7 @@ _Example_
|
|||||||
```
|
```
|
||||||
--memory size=0
|
--memory size=0
|
||||||
--memory-zone id=mem0,size=1G id=mem1,size=1G id=mem2,size=1G
|
--memory-zone id=mem0,size=1G id=mem1,size=1G id=mem2,size=1G
|
||||||
--numa guest_numa_id=0,memory_zones=mem0:mem2 guest_numa_id=1,memory_zones=mem1
|
--numa guest_numa_id=0,memory_zones=[mem0,mem2] guest_numa_id=1,memory_zones=mem1
|
||||||
```
|
```
|
||||||
|
|
||||||
### `sgx_epc_sections`
|
### `sgx_epc_sections`
|
||||||
@@ -520,13 +529,16 @@ which must be seen by the guest as belonging to the NUMA node `guest_numa_id`.
|
|||||||
|
|
||||||
Multiple values can be provided to define the list. Each value is a string
|
Multiple values can be provided to define the list. Each value is a string
|
||||||
referring to an existing SGX EPC section identifier. Values are separated from
|
referring to an existing SGX EPC section identifier. Values are separated from
|
||||||
each other with the `:` separator.
|
each other with the `,` separator.
|
||||||
|
|
||||||
|
As soon as one tries to describe a list of values, `[` and `]` must be used to
|
||||||
|
demarcate the list.
|
||||||
|
|
||||||
_Example_
|
_Example_
|
||||||
|
|
||||||
```
|
```
|
||||||
--sgx-epc id=epc0,size=32M id=epc1,size=64M id=epc2,size=32M
|
--sgx-epc id=epc0,size=32M id=epc1,size=64M id=epc2,size=32M
|
||||||
--numa guest_numa_id=0,sgx_epc_sections=epc1 guest_numa_id=1,sgx_epc_sections=epc0:epc2
|
--numa guest_numa_id=0,sgx_epc_sections=epc1 guest_numa_id=1,sgx_epc_sections=[epc0,epc2]
|
||||||
```
|
```
|
||||||
|
|
||||||
### PCI bus
|
### PCI bus
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ before the snapshot was performed.
|
|||||||
This feature is important for the project as it establishes the first step
|
This feature is important for the project as it establishes the first step
|
||||||
towards the support for live migration.
|
towards the support for live migration.
|
||||||
|
|
||||||
## Snapshot a Cloud-Hypervisor VM
|
## Snapshot a Cloud Hypervisor VM
|
||||||
|
|
||||||
First thing, we must run a Cloud-Hypervisor VM:
|
First thing, we must run a Cloud Hypervisor VM:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./cloud-hypervisor \
|
./cloud-hypervisor \
|
||||||
@@ -54,7 +54,7 @@ drwxr-xr-x 47 foo bar 4096 Jul 22 11:47 ../
|
|||||||
In this particular example, we can observe that 2 memory region files were
|
In this particular example, we can observe that 2 memory region files were
|
||||||
created. That is explained by the size of the guest RAM, which is 4GiB in this
|
created. That is explained by the size of the guest RAM, which is 4GiB in this
|
||||||
case. Because it exceeds 3GiB (which is where we can find a ~1GiB memory hole),
|
case. Because it exceeds 3GiB (which is where we can find a ~1GiB memory hole),
|
||||||
Cloud-Hypervisor needs 2 distinct memory regions to be created. Each memory
|
Cloud Hypervisor needs 2 distinct memory regions to be created. Each memory
|
||||||
region's content is stored through a dedicated file, which explains why we end
|
region's content is stored through a dedicated file, which explains why we end
|
||||||
up with 2 different files, the first one containing the guest RAM range 0-3GiB
|
up with 2 different files, the first one containing the guest RAM range 0-3GiB
|
||||||
and the second one containing the guest RAM range 3-4GiB.
|
and the second one containing the guest RAM range 3-4GiB.
|
||||||
@@ -65,7 +65,7 @@ with the correct amount of CPUs, RAM, and other expected devices. The state
|
|||||||
bits are used to restore each component in the state it was left before the
|
bits are used to restore each component in the state it was left before the
|
||||||
snapshot occurred.
|
snapshot occurred.
|
||||||
|
|
||||||
## Restore a Cloud-Hypervisor VM
|
## Restore a Cloud Hypervisor VM
|
||||||
|
|
||||||
Given that one has access to an existing snapshot in `/home/foo/snapshot`,
|
Given that one has access to an existing snapshot in `/home/foo/snapshot`,
|
||||||
it is possible to create a new VM based on this snapshot with the following
|
it is possible to create a new VM based on this snapshot with the following
|
||||||
|
|||||||
39
docs/uefi.md
39
docs/uefi.md
@@ -17,7 +17,7 @@ cd edk2
|
|||||||
. edksetup.sh
|
. edksetup.sh
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
|
|
||||||
echo "ACTIVE_PLATFORM=OvmfPkg/OvmfCh.dsc" >> Conf/target.txt
|
echo "ACTIVE_PLATFORM=OvmfPkg/CloudHv/CloudHvX64.dsc" >> Conf/target.txt
|
||||||
echo "TARGET_ARCH=X64" >> Conf/target.txt
|
echo "TARGET_ARCH=X64" >> Conf/target.txt
|
||||||
echo "TOOL_CHAIN_TAG=GCC5" >> Conf/target.txt
|
echo "TOOL_CHAIN_TAG=GCC5" >> Conf/target.txt
|
||||||
|
|
||||||
@@ -25,49 +25,16 @@ make -C ./BaseTools
|
|||||||
build
|
build
|
||||||
```
|
```
|
||||||
|
|
||||||
After the successful build, the resulting firmware binaries are available under `Build/OvmfCh/DEBUG_GCC5/FV` underneath the edk2 checkout.
|
After the successful build, the resulting firmware binaries are available under `Build/CloudHvX64/DEBUG_GCC5/FV` underneath the edk2 checkout.
|
||||||
|
|
||||||
## Using OVMF Binaries
|
## Using OVMF Binaries
|
||||||
|
|
||||||
Any UEFI capable image can be booted using the Cloud Hypervisor specific firmware. Windows guests under Cloud Hypervisor only support UEFI boot, therefore OVMF is mandatory there.
|
Any UEFI capable image can be booted using the Cloud Hypervisor specific firmware. Windows guests under Cloud Hypervisor only support UEFI boot, therefore OVMF is mandatory there.
|
||||||
|
|
||||||
To make Cloud Hypervisor use UEFI boot, pass the `OVMF.fd` file path as an argument to the `--kernel` option. The firmware file will be opened in read only mode.
|
To make Cloud Hypervisor use UEFI boot, pass the `CLOUDHV.fd` file path as an argument to the `--kernel` option. The firmware file will be opened in read only mode.
|
||||||
|
|
||||||
The same firmware can be used with Cloud Hypervisor or with QEMU. This is particularly useful if using QEMU for the preparation phase.
|
The same firmware can be used with Cloud Hypervisor or with QEMU. This is particularly useful if using QEMU for the preparation phase.
|
||||||
|
|
||||||
## Building UEFI Firmware with Compatibility Support Module (CSM)
|
|
||||||
|
|
||||||
CSM is a module that allows to boot legacy operating systems using the OVMF firmware. OVMF can embed a CSM build of SeaBIOS. To build the SeaBIOS with CSM support, add `CONFIG_CSM=y` to `.config` before the build. The outcome `out/Csm16.bin` is to be moved into `OvmfPkg/Csm/Csm16/Csm16.bin` before OVMF is built. Then, the OVMF build will have to be passed the `-D CSM_ENABLE` option in order to generate a legacy aware UEFI firmware. At the current stage, all the necessary patches are included in the Cloud Hypervisor specific [SeaBIOS branch](https://github.com/cloud-hypervisor/seabios/tree/ch). Taking into account the previous instructions, the modified command sequence to compile an OVMF binary with CSM support is the following one:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install uuid-dev nasm iasl build-essential python3-distutils git libncurses-dev
|
|
||||||
|
|
||||||
git clone https://github.com/cloud-hypervisor/seabios -b ch
|
|
||||||
cd seabios
|
|
||||||
make menuconfig
|
|
||||||
# Enable `CONFIG_CSM` and `CONFIG_QEMU_HARDWARE`
|
|
||||||
# Please make sure `python` is in your path
|
|
||||||
make CONFIG_CSM=y CONFIG_QEMU_HARDWARE=y
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
git clone https://github.com/cloud-hypervisor/edk2 -b ch
|
|
||||||
cd edk2
|
|
||||||
. edksetup.sh
|
|
||||||
git submodule update --init --recursive
|
|
||||||
cp ../seabios/out/Csm16.bin OvmfPkg/Csm/Csm16/
|
|
||||||
|
|
||||||
echo "ACTIVE_PLATFORM=OvmfPkg/OvmfCh.dsc" >> Conf/target.txt
|
|
||||||
echo "TARGET_ARCH=X64" >> Conf/target.txt
|
|
||||||
echo "TOOL_CHAIN_TAG=GCC5" >> Conf/target.txt
|
|
||||||
|
|
||||||
make -C ./BaseTools
|
|
||||||
build -DCSM_ENABLE
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Please note, that the CSM support has currently only been tested with Linux guests. There are no plans to provide legacy support for other OSes (e.g. Windows).
|
|
||||||
|
|
||||||
# Links
|
# Links
|
||||||
|
|
||||||
- [OVMF wiki](https://github.com/tianocore/tianocore.github.io/wiki/OVMF)
|
- [OVMF wiki](https://github.com/tianocore/tianocore.github.io/wiki/OVMF)
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ Use SPDK: https://github.com/spdk/spdk
|
|||||||
|
|
||||||
Compile with `./configure --with-vfio-user`
|
Compile with `./configure --with-vfio-user`
|
||||||
|
|
||||||
Create an NVMe controller listening on a vfio-user socket with a simple block device:
|
Create an NVMe controller listening on a vfio-user socket with a simple AIO block device in spdk.
|
||||||
|
More details of configuring SPDK bdev can be viewed in [SPDK bdev](https://spdk.io/doc/bdev.html).
|
||||||
|
More details of setting SPDK NVMe-oF target can be viewed in [SDPK NVMe-oF tgt](https://spdk.io/doc/nvmf.html).
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo scripts/setup.sh
|
sudo scripts/setup.sh
|
||||||
|
|||||||
54
docs/vfio.md
54
docs/vfio.md
@@ -36,14 +36,22 @@ Now that we have identified the device, we must unbind it from its native driver
|
|||||||
First we add VFIO support to the host:
|
First we add VFIO support to the host:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo modprobe vfio_pci
|
# modprobe -r vfio_pci
|
||||||
$ sudo modprobe vfio_iommu_type1 allow_unsafe_interrupts
|
# modprobe -r vfio_iommu_type1
|
||||||
|
# modprobe vfio_iommu_type1 allow_unsafe_interrupts
|
||||||
|
# modprobe vfio_pci
|
||||||
|
```
|
||||||
|
|
||||||
|
In case the VFIO drivers are built-in, enable unsafe interrupts with:
|
||||||
|
|
||||||
|
```
|
||||||
|
# echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
|
||||||
```
|
```
|
||||||
|
|
||||||
Then we unbind it from its native driver:
|
Then we unbind it from its native driver:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ echo 0000:01:00.0 > /sys/bus/pci/devices/0000\:01\:00.0/driver/unbind
|
# echo 0000:01:00.0 > /sys/bus/pci/devices/0000\:01\:00.0/driver/unbind
|
||||||
```
|
```
|
||||||
|
|
||||||
And finally we bind it to the VFIO driver. To do that we first need to get the
|
And finally we bind it to the VFIO driver. To do that we first need to get the
|
||||||
@@ -53,8 +61,14 @@ device's VID (Vendor ID) and PID (Product ID):
|
|||||||
$ lspci -n -s 01:00.0
|
$ lspci -n -s 01:00.0
|
||||||
01:00.0 ff00: 10ec:525a (rev 01)
|
01:00.0 ff00: 10ec:525a (rev 01)
|
||||||
|
|
||||||
$ echo 10ec 525a > /sys/bus/pci/drivers/vfio-pci/new_id
|
# echo 10ec 525a > /sys/bus/pci/drivers/vfio-pci/new_id
|
||||||
$ echo 0000:01:00.0 > /sys/bus/pci/drivers/vfio-pci/bind
|
```
|
||||||
|
|
||||||
|
If you have more than one device with the same `vendorID`/`deviceID`, starting
|
||||||
|
with the second device, the binding is performed as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
# echo 0000:02:00.0 > /sys/bus/pci/drivers/vfio-pci/bind
|
||||||
```
|
```
|
||||||
|
|
||||||
Now the device is managed by the VFIO framework.
|
Now the device is managed by the VFIO framework.
|
||||||
@@ -79,3 +93,33 @@ takes the device's sysfs path as an argument. In our example it is
|
|||||||
The guest kernel will then detect the card reader on its PCI bus and provided
|
The guest kernel will then detect the card reader on its PCI bus and provided
|
||||||
that support for this device is enabled, it will probe and enable it for the
|
that support for this device is enabled, it will probe and enable it for the
|
||||||
guest to use.
|
guest to use.
|
||||||
|
|
||||||
|
In case you want to pass multiple devices, here is the correct syntax:
|
||||||
|
|
||||||
|
```
|
||||||
|
--device path=/sys/bus/pci/devices/0000:01:00.0/ path=/sys/bus/pci/devices/0000:02:00.0/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple devices in the same IOMMU group
|
||||||
|
|
||||||
|
There are cases where multiple devices can be found under the same IOMMU group.
|
||||||
|
This happens often with graphics card embedding an audio controller.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lspci
|
||||||
|
[...]
|
||||||
|
01:00.0 VGA compatible controller: NVIDIA Corporation GK208B [GeForce GT 710] (rev a1)
|
||||||
|
01:00.1 Audio device: NVIDIA Corporation GK208 HDMI/DP Audio Controller (rev a1)
|
||||||
|
[...]
|
||||||
|
```
|
||||||
|
|
||||||
|
This is usually exposed as follows through `sysfs`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ls /sys/kernel/iommu_groups/22/devices/
|
||||||
|
0000:01:00.0 0000:01:00.1
|
||||||
|
```
|
||||||
|
|
||||||
|
This means these two devices are under the same IOMMU group 22. In such case,
|
||||||
|
it is important to bind both devices to VFIO and pass them both through the
|
||||||
|
VM, otherwise this could cause some functional and security issues.
|
||||||
@@ -69,12 +69,16 @@ make
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Set the SPDK environment
|
### Set the SPDK environment
|
||||||
|
|
||||||
|
Run SPDK vhost target with 2 CPU cores, i.e., core 0 and 1.
|
||||||
```bash
|
```bash
|
||||||
sudo HUGEMEM=2048 scripts/setup.sh
|
sudo HUGEMEM=2048 scripts/setup.sh
|
||||||
sudo ./build/bin/vhost -S /var/tmp -s 1024 -m 0x3 &
|
sudo ./build/bin/vhost -S /var/tmp -s 1024 -m 0x3 &
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create 512M block device
|
### Create 512M block device
|
||||||
|
|
||||||
|
Create a 512M (first parameter) block device with 512 bytes (second parameter) block size.
|
||||||
```bash
|
```bash
|
||||||
sudo scripts/rpc.py bdev_malloc_create 512 512 -b Malloc0
|
sudo scripts/rpc.py bdev_malloc_create 512 512 -b Malloc0
|
||||||
sudo scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 vhost.1 Malloc0
|
sudo scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 vhost.1 Malloc0
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ The basic command to boot a Windows image. The configuration section should be c
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
cloud-hypervisor \
|
cloud-hypervisor \
|
||||||
--kernel ./$OVMF_DIR/OVMF.fd \
|
--kernel ./$OVMF_DIR/CLOUDHV.fd \
|
||||||
--disk path=./$IMG_FILE \
|
--disk path=./$IMG_FILE \
|
||||||
--cpus boot=1,kvm_hyperv=on \
|
--cpus boot=1,kvm_hyperv=on \
|
||||||
--memory size=4G \
|
--memory size=4G \
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ authors = ["The Cloud Hypervisor Authors"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
serde = { version = "1.0.130", features = ["rc"] }
|
serde = { version = "1.0.133", features = ["rc"] }
|
||||||
serde_derive = "1.0.130"
|
serde_derive = "1.0.133"
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.75"
|
||||||
|
|||||||
233
fuzz/Cargo.lock
generated
233
fuzz/Cargo.lock
generated
@@ -9,20 +9,11 @@ dependencies = [
|
|||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.44"
|
version = "1.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
|
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "api_client"
|
name = "api_client"
|
||||||
@@ -33,15 +24,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "577b08a4acd7b99869f863c50011b01eb73424ccc798ecd996f2e24817adfca7"
|
checksum = "510c76ecefdceada737ea728f4f9a84bd2e1ef29f1ba555e560940fe279954de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6df5aef5c5830360ce5218cecb8f018af3438af5686ae945094affc86fdec63"
|
checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arch"
|
name = "arch"
|
||||||
@@ -77,6 +68,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "1.3.3"
|
version = "1.3.3"
|
||||||
@@ -105,6 +102,7 @@ dependencies = [
|
|||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -118,9 +116,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.71"
|
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 = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -130,23 +128,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.3"
|
version = "3.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"lazy_static",
|
||||||
|
"os_str_bytes",
|
||||||
"strsim",
|
"strsim",
|
||||||
"term_size",
|
"termcolor",
|
||||||
|
"terminal_size",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"unicode-width",
|
|
||||||
"vec_map",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloud-hypervisor"
|
name = "cloud-hypervisor"
|
||||||
version = "18.0.0"
|
version = "20.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"api_client",
|
"api_client",
|
||||||
@@ -178,6 +177,7 @@ dependencies = [
|
|||||||
"seccompiler",
|
"seccompiler",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -185,9 +185,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32c"
|
name = "crc32c"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "210cdf933e6a81212bfabf90cd8762f471b5922e5f6b709547673ad8e04b9448"
|
checksum = "ee6b9c9389584bcba988bd0836086789b7f87ad91892d6a83d5291dbb24524b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
@@ -246,9 +246,9 @@ checksum = "b643857cf70949306b81d7e92cb9d47add673868edac9863c4a49c42feaf3f1e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -256,10 +256,16 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hashbrown"
|
||||||
version = "0.1.19"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7a30908dbce072eca83216eab939d2290080e00ca71611b96a09e5cdce5f3fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -293,6 +299,16 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-uring"
|
name = "io-uring"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@@ -305,9 +321,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-bindings"
|
name = "kvm-bindings"
|
||||||
@@ -321,9 +337,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kvm-ioctls"
|
name = "kvm-ioctls"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-vmm/kvm-ioctls?branch=main#d22ef1f51852dfb055da38004e1a4fed81246f81"
|
||||||
checksum = "48dc14f9047df1873cf6942caccc7431d19c3d496ca7a0d162260c4cf0f64b76"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -338,9 +353,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.103"
|
version = "0.2.112"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -371,6 +386,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micro_http"
|
name = "micro_http"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -401,6 +422,7 @@ dependencies = [
|
|||||||
"versionize",
|
"versionize",
|
||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vm-virtio",
|
"vm-virtio",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
@@ -408,14 +430,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.8.0"
|
version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option_parser"
|
name = "option_parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_str_bytes"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pci"
|
name = "pci"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -440,9 +471,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.30"
|
version = "1.0.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
@@ -460,9 +491,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.10"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -489,18 +520,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.2.3"
|
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 = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
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 = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "seccompiler"
|
name = "seccompiler"
|
||||||
@@ -513,30 +544,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||||
dependencies = [
|
|
||||||
"semver-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver-parser"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.130"
|
version = "1.0.133"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.130"
|
version = "1.0.133"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -545,9 +567,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.68"
|
version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -556,9 +578,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.10"
|
version = "0.3.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
|
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -581,15 +603,15 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.80"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -597,10 +619,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "term_size"
|
name = "termcolor"
|
||||||
version = "0.3.2"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -608,12 +639,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"term_size",
|
"terminal_size",
|
||||||
"unicode-width",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -636,12 +666,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -657,12 +681,6 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vec_map"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "versionize"
|
name = "versionize"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -692,9 +710,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-bindings"
|
name = "vfio-bindings"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a21f546f2bda37f5a8cfb138c87f95b8e34d2d78d6a7a92ba3785f4e08604a7"
|
checksum = "43449b404c488f70507dca193debd4bea361fe8089869b947adc19720e464bce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
@@ -702,7 +720,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vfio-ioctls"
|
name = "vfio-ioctls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#d51c1fad37be30c20385c55a217e2d90972ea31d"
|
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#8f7f2210ebe71660938b05b2ed7eec9253478bc5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"kvm-bindings",
|
"kvm-bindings",
|
||||||
@@ -745,9 +763,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d23ddeb452fb4f837526c6298cc8a2f4948e5595b0328a3d61b5eebe51874d7"
|
checksum = "3b56bf8f178fc500fe14505fca8b00dec76fc38f2304f461c8d9d7547982311d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -786,6 +804,7 @@ dependencies = [
|
|||||||
"versionize_derive",
|
"versionize_derive",
|
||||||
"vhost",
|
"vhost",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -794,6 +813,15 @@ dependencies = [
|
|||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtio-queue"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"vm-memory",
|
||||||
|
"vmm-sys-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-allocator"
|
name = "vm-allocator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -824,9 +852,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#720e48e435b791ec6cb
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vm-memory"
|
name = "vm-memory"
|
||||||
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 = "0a8ebcb86ca457f9d6e14cf97009f679952eba42f0113de5db596e514cd0e43b"
|
checksum = "339d4349c126fdcd87e034631d7274370cf19eb0e87b33166bcd956589fc72c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -853,6 +881,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"virtio-bindings",
|
"virtio-bindings",
|
||||||
|
"virtio-queue",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -893,6 +922,7 @@ dependencies = [
|
|||||||
"vfio_user",
|
"vfio_user",
|
||||||
"vhdx",
|
"vhdx",
|
||||||
"virtio-devices",
|
"virtio-devices",
|
||||||
|
"virtio-queue",
|
||||||
"vm-allocator",
|
"vm-allocator",
|
||||||
"vm-device",
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
@@ -935,6 +965,15 @@ 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 = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|||||||
@@ -10,21 +10,23 @@ cargo-fuzz = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
block_util = { path = "../block_util" }
|
block_util = { path = "../block_util" }
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
libfuzzer-sys = "0.4.2"
|
libfuzzer-sys = "0.4.2"
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
seccompiler = "0.2.0"
|
seccompiler = "0.2.0"
|
||||||
vhdx = { path = "../vhdx" }
|
vhdx = { path = "../vhdx" }
|
||||||
virtio-devices = { path = "../virtio-devices" }
|
virtio-devices = { path = "../virtio-devices" }
|
||||||
|
virtio-queue = { path = "../virtio-queue" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vm-memory = "0.6.0"
|
vm-memory = "0.7.0"
|
||||||
|
|
||||||
[dependencies.cloud-hypervisor]
|
[dependencies.cloud-hypervisor]
|
||||||
path = ".."
|
path = ".."
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", features = ["with-serde", "fam-wrappers"] }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", features = ["with-serde", "fam-wrappers"] }
|
||||||
|
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" }
|
||||||
|
|
||||||
# Prevent this from interfering with workspaces
|
# Prevent this from interfering with workspaces
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
|
use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
|
||||||
use vm_memory::{Bytes, GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
|
use virtio_queue::{Queue, QueueState};
|
||||||
use vm_virtio::Queue;
|
use vm_memory::{bitmap::AtomicBitmap, Bytes, GuestAddress, GuestMemoryAtomic};
|
||||||
use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
|
use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
|
||||||
|
|
||||||
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||||
|
|
||||||
const MEM_SIZE: u64 = 256 * 1024 * 1024;
|
const MEM_SIZE: u64 = 256 * 1024 * 1024;
|
||||||
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
|
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
|
||||||
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
|
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
|
||||||
@@ -73,10 +75,14 @@ fuzz_target!(|bytes| {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut q = Queue::new(QUEUE_SIZE);
|
let guest_memory = GuestMemoryAtomic::new(mem);
|
||||||
q.ready = true;
|
|
||||||
q.size = QUEUE_SIZE / 2;
|
let mut q = Queue::<
|
||||||
q.max_size = QUEUE_SIZE;
|
GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
QueueState,
|
||||||
|
>::new(guest_memory.clone(), QUEUE_SIZE);
|
||||||
|
q.state.ready = true;
|
||||||
|
q.state.size = QUEUE_SIZE / 2;
|
||||||
|
|
||||||
let queue_evts: Vec<EventFd> = vec![EventFd::new(0).unwrap()];
|
let queue_evts: Vec<EventFd> = vec![EventFd::new(0).unwrap()];
|
||||||
let queue_fd = queue_evts[0].as_raw_fd();
|
let queue_fd = queue_evts[0].as_raw_fd();
|
||||||
@@ -102,7 +108,7 @@ fuzz_target!(|bytes| {
|
|||||||
|
|
||||||
block
|
block
|
||||||
.activate(
|
.activate(
|
||||||
GuestMemoryAtomic::new(mem),
|
guest_memory,
|
||||||
Arc::new(NoopVirtioInterrupt {}),
|
Arc::new(NoopVirtioInterrupt {}),
|
||||||
vec![q],
|
vec![q],
|
||||||
queue_evts,
|
queue_evts,
|
||||||
@@ -134,7 +140,7 @@ impl VirtioInterrupt for NoopVirtioInterrupt {
|
|||||||
fn trigger(
|
fn trigger(
|
||||||
&self,
|
&self,
|
||||||
_int_type: &VirtioInterruptType,
|
_int_type: &VirtioInterruptType,
|
||||||
_queue: Option<&Queue>,
|
_queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||||
) -> std::result::Result<(), std::io::Error> {
|
) -> std::result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,19 @@ mshv = ["mshv-ioctls", "mshv-bindings"]
|
|||||||
tdx = []
|
tdx = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.52"
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
kvm-ioctls = { version = "0.10.0", optional = true }
|
kvm-ioctls = { version = "0.11.0", optional = true }
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", features = ["with-serde", "fam-wrappers"], optional = true }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0", 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.130", features = ["rc"] }
|
serde = { version = "1.0.133", features = ["rc"] }
|
||||||
serde_derive = "1.0.130"
|
serde_derive = "1.0.133"
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.75"
|
||||||
vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic"] }
|
||||||
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||||
|
|||||||
@@ -18,7 +18,18 @@ pub struct Exception<T: Debug> {
|
|||||||
|
|
||||||
impl<T: Debug> Display for Exception<T> {
|
impl<T: Debug> Display for Exception<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "Exception {:?} at IP {:#x}", self.vector, self.ip)
|
write!(
|
||||||
|
f,
|
||||||
|
"Exception {:?} at IP {:#x}{}{}",
|
||||||
|
self.vector,
|
||||||
|
self.ip,
|
||||||
|
self.error
|
||||||
|
.map(|e| format!(": error {:x}", e))
|
||||||
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
|
self.payload
|
||||||
|
.map(|payload| format!(": payload {:x}", payload))
|
||||||
|
.unwrap_or_else(|| "".to_owned())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -653,8 +653,6 @@ mod mock_vmm {
|
|||||||
state: Arc<Mutex<CpuState>>,
|
state: Arc<Mutex<CpuState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for MockVmm {}
|
|
||||||
|
|
||||||
pub type MockResult = Result<(), EmulationError<Exception>>;
|
pub type MockResult = Result<(), EmulationError<Exception>>;
|
||||||
|
|
||||||
impl MockVmm {
|
impl MockVmm {
|
||||||
|
|||||||
@@ -174,6 +174,16 @@ pub enum HypervisorCpuError {
|
|||||||
#[error("Failed to get debug registers: {0}")]
|
#[error("Failed to get debug registers: {0}")]
|
||||||
GetDebugRegs(#[source] anyhow::Error),
|
GetDebugRegs(#[source] anyhow::Error),
|
||||||
///
|
///
|
||||||
|
/// Setting misc register error
|
||||||
|
///
|
||||||
|
#[error("Failed to set misc registers: {0}")]
|
||||||
|
SetMiscRegs(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
|
/// Getting misc register error
|
||||||
|
///
|
||||||
|
#[error("Failed to get misc registers: {0}")]
|
||||||
|
GetMiscRegs(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
/// Write to Guest Mem
|
/// Write to Guest Mem
|
||||||
///
|
///
|
||||||
#[error("Failed to write to Guest Mem at: {0}")]
|
#[error("Failed to write to Guest Mem at: {0}")]
|
||||||
@@ -433,4 +443,9 @@ pub trait Vcpu: Send + Sync {
|
|||||||
/// Return suspend registers(explicit and intercept suspend registers)
|
/// Return suspend registers(explicit and intercept suspend registers)
|
||||||
///
|
///
|
||||||
fn get_suspend_regs(&self) -> Result<SuspendRegisters>;
|
fn get_suspend_regs(&self) -> Result<SuspendRegisters>;
|
||||||
|
#[cfg(feature = "kvm")]
|
||||||
|
///
|
||||||
|
/// Set the "immediate_exit" state
|
||||||
|
///
|
||||||
|
fn set_immediate_exit(&self, exit: bool);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,23 +26,33 @@ pub use kvm_bindings::{
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
|
||||||
|
|
||||||
// Following are macros that help with getting the ID of a aarch64 core register.
|
|
||||||
// The core register are represented by the user_pt_regs structure. Look for it in
|
|
||||||
// arch/arm64/include/uapi/asm/ptrace.h.
|
|
||||||
|
|
||||||
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
|
||||||
// an instance of that structure.
|
// an instance of that structure.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! offset__of {
|
macro_rules! offset__of {
|
||||||
($str:ty, $($field:ident)+) => ({
|
($str:ty, $($field:ident)+) => ({
|
||||||
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
|
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
|
||||||
let tmp = unsafe { tmp.assume_init() };
|
let base = tmp.as_ptr();
|
||||||
let base = &tmp as *const _ as usize;
|
|
||||||
let member = &tmp.$($field)* as *const _ as usize;
|
|
||||||
|
|
||||||
member - base
|
// Avoid warnings when nesting `unsafe` blocks.
|
||||||
|
#[allow(unused_unsafe)]
|
||||||
|
// SAFETY: The pointer is valid and aligned, just not initialised. Using `addr_of` ensures
|
||||||
|
// that we don't actually read from `base` (which would be UB) nor create an intermediate
|
||||||
|
// reference.
|
||||||
|
let member = unsafe { core::ptr::addr_of!((*base).$($field)*) } as *const u8;
|
||||||
|
|
||||||
|
// Avoid warnings when nesting `unsafe` blocks.
|
||||||
|
#[allow(unused_unsafe)]
|
||||||
|
// SAFETY: The two pointers are within the same allocated object `tmp`. All requirements
|
||||||
|
// from offset_from are upheld.
|
||||||
|
unsafe { member.offset_from(base as *const u8) as usize }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Following are macros that help with getting the ID of a aarch64 core register.
|
||||||
|
// The core register are represented by the user_pt_regs structure. Look for it in
|
||||||
|
// arch/arm64/include/uapi/asm/ptrace.h.
|
||||||
|
|
||||||
// Get the ID of a core register
|
// Get the ID of a core register
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! arm64_core_reg_id {
|
macro_rules! arm64_core_reg_id {
|
||||||
@@ -115,9 +125,13 @@ pub fn is_system_register(regid: u64) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let size = regid & KVM_REG_SIZE_MASK;
|
let size = regid & KVM_REG_SIZE_MASK;
|
||||||
if size != KVM_REG_SIZE_U32 && size != KVM_REG_SIZE_U64 {
|
|
||||||
panic!("Unexpected register size for system register {}", size);
|
assert!(
|
||||||
}
|
!(size != KVM_REG_SIZE_U32 && size != KVM_REG_SIZE_U64),
|
||||||
|
"Unexpected register size for system register {}",
|
||||||
|
size
|
||||||
|
);
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ use std::result;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use vm_memory::Address;
|
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
// x86_64 dependencies
|
// x86_64 dependencies
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -47,9 +45,7 @@ use kvm_bindings::{
|
|||||||
kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP,
|
kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP,
|
||||||
};
|
};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{
|
use x86_64::{check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters};
|
||||||
check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters, KVM_TSS_ADDRESS,
|
|
||||||
};
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState as CpuState,
|
CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState as CpuState,
|
||||||
@@ -139,6 +135,15 @@ pub struct KvmVm {
|
|||||||
/// vm.set/get().unwrap()
|
/// vm.set/get().unwrap()
|
||||||
///
|
///
|
||||||
impl vm::Vm for KvmVm {
|
impl vm::Vm for KvmVm {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
///
|
||||||
|
/// Sets the address of the one-page region in the VM's address space.
|
||||||
|
///
|
||||||
|
fn set_identity_map_address(&self, address: u64) -> vm::Result<()> {
|
||||||
|
self.fd
|
||||||
|
.set_identity_map_address(address)
|
||||||
|
.map_err(|e| vm::HypervisorVmError::SetIdentityMapAddress(e.into()))
|
||||||
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Sets the address of the three-page region in the VM's address space.
|
/// Sets the address of the three-page region in the VM's address space.
|
||||||
@@ -238,6 +243,9 @@ impl vm::Vm for KvmVm {
|
|||||||
irq_routing[0].nr = entries.len() as u32;
|
irq_routing[0].nr = entries.len() as u32;
|
||||||
irq_routing[0].flags = 0;
|
irq_routing[0].flags = 0;
|
||||||
|
|
||||||
|
// SAFETY: irq_routing initialized with entries.len() and now it is being turned into
|
||||||
|
// entries_slice with entries.len() again. It is guaranteed to be large enough to hold
|
||||||
|
// everything from entries.
|
||||||
unsafe {
|
unsafe {
|
||||||
let entries_slice: &mut [kvm_irq_routing_entry] =
|
let entries_slice: &mut [kvm_irq_routing_entry] =
|
||||||
irq_routing[0].entries.as_mut_slice(entries.len());
|
irq_routing[0].entries.as_mut_slice(entries.len());
|
||||||
@@ -302,7 +310,7 @@ impl vm::Vm for KvmVm {
|
|||||||
region.flags = 0;
|
region.flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe because guest regions are guaranteed not to overlap.
|
// SAFETY: Safe because guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.fd
|
self.fd
|
||||||
.set_user_memory_region(region)
|
.set_user_memory_region(region)
|
||||||
@@ -320,7 +328,7 @@ impl vm::Vm for KvmVm {
|
|||||||
|
|
||||||
// Setting the size to 0 means "remove"
|
// Setting the size to 0 means "remove"
|
||||||
region.memory_size = 0;
|
region.memory_size = 0;
|
||||||
// Safe because guest regions are guaranteed not to overlap.
|
// SAFETY: Safe because guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.fd
|
self.fd
|
||||||
.set_user_memory_region(region)
|
.set_user_memory_region(region)
|
||||||
@@ -350,10 +358,6 @@ impl vm::Vm for KvmVm {
|
|||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn enable_split_irq(&self) -> vm::Result<()> {
|
fn enable_split_irq(&self) -> vm::Result<()> {
|
||||||
// Set TSS
|
|
||||||
self.fd
|
|
||||||
.set_tss_address(KVM_TSS_ADDRESS.raw_value() as usize)
|
|
||||||
.map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?;
|
|
||||||
// Create split irqchip
|
// Create split irqchip
|
||||||
// Only the local APIC is emulated in kernel, both PICs and IOAPIC
|
// Only the local APIC is emulated in kernel, both PICs and IOAPIC
|
||||||
// are not.
|
// are not.
|
||||||
@@ -434,7 +438,7 @@ impl vm::Vm for KvmVm {
|
|||||||
userspace_addr: s.userspace_addr,
|
userspace_addr: s.userspace_addr,
|
||||||
flags: KVM_MEM_LOG_DIRTY_PAGES,
|
flags: KVM_MEM_LOG_DIRTY_PAGES,
|
||||||
};
|
};
|
||||||
// Safe because guest regions are guaranteed not to overlap.
|
// SAFETY: Safe because guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.fd
|
self.fd
|
||||||
.set_user_memory_region(region)
|
.set_user_memory_region(region)
|
||||||
@@ -458,7 +462,7 @@ impl vm::Vm for KvmVm {
|
|||||||
userspace_addr: s.userspace_addr,
|
userspace_addr: s.userspace_addr,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
};
|
};
|
||||||
// Safe because guest regions are guaranteed not to overlap.
|
// SAFETY: Safe because guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.fd
|
self.fd
|
||||||
.set_user_memory_region(region)
|
.set_user_memory_region(region)
|
||||||
@@ -574,6 +578,7 @@ fn tdx_command(
|
|||||||
metadata,
|
metadata,
|
||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
|
// SAFETY: FFI call. All input parameters are valid.
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
ioctl_with_val(
|
ioctl_with_val(
|
||||||
fd,
|
fd,
|
||||||
@@ -1046,9 +1051,16 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
/// potential soft lockups when being resumed.
|
/// potential soft lockups when being resumed.
|
||||||
///
|
///
|
||||||
fn notify_guest_clock_paused(&self) -> cpu::Result<()> {
|
fn notify_guest_clock_paused(&self) -> cpu::Result<()> {
|
||||||
self.fd
|
if let Err(e) = self.fd.kvmclock_ctrl() {
|
||||||
.kvmclock_ctrl()
|
// Linux kernel returns -EINVAL if the PV clock isn't yet initialised
|
||||||
.map_err(|e| cpu::HypervisorCpuError::NotifyGuestClockPaused(e.into()))
|
// which could be because we're still in firmware or the guest doesn't
|
||||||
|
// use KVM clock.
|
||||||
|
if e.errno() != libc::EINVAL {
|
||||||
|
return Err(cpu::HypervisorCpuError::NotifyGuestClockPaused(e.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
||||||
@@ -1562,6 +1574,13 @@ impl cpu::Vcpu for KvmVcpu {
|
|||||||
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
|
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
|
||||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set the "immediate_exit" state
|
||||||
|
///
|
||||||
|
fn set_immediate_exit(&self, exit: bool) {
|
||||||
|
self.fd.set_kvm_immediate_exit(exit.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Device struct for KVM
|
/// Device struct for KVM
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB};
|
||||||
use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
|
use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use vm_memory::GuestAddress;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
|
||||||
@@ -92,8 +91,6 @@ impl SegmentRegisterOps for SegmentRegister {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const KVM_TSS_ADDRESS: GuestAddress = GuestAddress(0xfffb_d000);
|
|
||||||
|
|
||||||
pub fn boot_msr_entries() -> MsrEntries {
|
pub fn boot_msr_entries() -> MsrEntries {
|
||||||
MsrEntries::from_entries(&[
|
MsrEntries::from_entries(&[
|
||||||
msr!(msr_index::MSR_IA32_SYSENTER_CS),
|
msr!(msr_index::MSR_IA32_SYSENTER_CS),
|
||||||
@@ -127,6 +124,15 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
|
|||||||
if !kvm.check_extension(Cap::SplitIrqchip) {
|
if !kvm.check_extension(Cap::SplitIrqchip) {
|
||||||
return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip));
|
return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip));
|
||||||
}
|
}
|
||||||
|
if !kvm.check_extension(Cap::SetIdentityMapAddr) {
|
||||||
|
return Err(KvmError::CapabilityMissing(Cap::SetIdentityMapAddr));
|
||||||
|
}
|
||||||
|
if !kvm.check_extension(Cap::SetTssAddr) {
|
||||||
|
return Err(KvmError::CapabilityMissing(Cap::SetTssAddr));
|
||||||
|
}
|
||||||
|
if !kvm.check_extension(Cap::ImmediateExit) {
|
||||||
|
return Err(KvmError::CapabilityMissing(Cap::ImmediateExit));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT => {
|
hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT => {
|
||||||
let info = x.to_ioport_info().unwrap();
|
let info = x.to_ioport_info().unwrap();
|
||||||
let access_info = info.access_info;
|
let access_info = info.access_info;
|
||||||
|
// SAFETY: access_info is valid, otherwise we won't be here
|
||||||
let len = unsafe { access_info.__bindgen_anon_1.access_size() } as usize;
|
let len = unsafe { access_info.__bindgen_anon_1.access_size() } as usize;
|
||||||
let is_write = info.header.intercept_access_type == 1;
|
let is_write = info.header.intercept_access_type == 1;
|
||||||
let port = info.port_number;
|
let port = info.port_number;
|
||||||
@@ -342,12 +343,15 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if unsafe { access_info.__bindgen_anon_1.string_op() } == 1 {
|
// SAFETY: access_info is valid, otherwise we won't be here
|
||||||
panic!("String IN/OUT not supported");
|
assert!(
|
||||||
}
|
(unsafe { access_info.__bindgen_anon_1.string_op() } != 1),
|
||||||
if unsafe { access_info.__bindgen_anon_1.rep_prefix() } == 1 {
|
"String IN/OUT not supported"
|
||||||
panic!("Rep IN/OUT not supported");
|
);
|
||||||
}
|
assert!(
|
||||||
|
(unsafe { access_info.__bindgen_anon_1.rep_prefix() } != 1),
|
||||||
|
"Rep IN/OUT not supported"
|
||||||
|
);
|
||||||
|
|
||||||
if is_write {
|
if is_write {
|
||||||
let data = (info.rax as u32).to_le_bytes();
|
let data = (info.rax as u32).to_le_bytes();
|
||||||
@@ -506,6 +510,13 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
self.set_xcrs(&state.xcrs)?;
|
self.set_xcrs(&state.xcrs)?;
|
||||||
self.set_lapic(&state.lapic)?;
|
self.set_lapic(&state.lapic)?;
|
||||||
self.set_xsave(&state.xsave)?;
|
self.set_xsave(&state.xsave)?;
|
||||||
|
// These registers are global and needed to be set only for first VCPU
|
||||||
|
// as Microsoft Hypervisor allows setting this regsier for only one VCPU
|
||||||
|
if self.vp_index == 0 {
|
||||||
|
self.fd
|
||||||
|
.set_misc_regs(&state.misc)
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::SetMiscRegs(e.into()))?
|
||||||
|
}
|
||||||
self.fd
|
self.fd
|
||||||
.set_debug_regs(&state.dbg)
|
.set_debug_regs(&state.dbg)
|
||||||
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
|
||||||
@@ -524,10 +535,15 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
self.get_msrs(&mut msrs)?;
|
self.get_msrs(&mut msrs)?;
|
||||||
let lapic = self.get_lapic()?;
|
let lapic = self.get_lapic()?;
|
||||||
let xsave = self.get_xsave()?;
|
let xsave = self.get_xsave()?;
|
||||||
|
let misc = self
|
||||||
|
.fd
|
||||||
|
.get_misc_regs()
|
||||||
|
.map_err(|e| cpu::HypervisorCpuError::GetMiscRegs(e.into()))?;
|
||||||
let dbg = self
|
let dbg = self
|
||||||
.fd
|
.fd
|
||||||
.get_debug_regs()
|
.get_debug_regs()
|
||||||
.map_err(|e| cpu::HypervisorCpuError::GetDebugRegs(e.into()))?;
|
.map_err(|e| cpu::HypervisorCpuError::GetDebugRegs(e.into()))?;
|
||||||
|
|
||||||
Ok(CpuState {
|
Ok(CpuState {
|
||||||
msrs,
|
msrs,
|
||||||
vcpu_events,
|
vcpu_events,
|
||||||
@@ -538,6 +554,7 @@ impl cpu::Vcpu for MshvVcpu {
|
|||||||
lapic,
|
lapic,
|
||||||
dbg,
|
dbg,
|
||||||
xsave,
|
xsave,
|
||||||
|
misc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -614,6 +631,7 @@ impl<'a> MshvEmulatorContext<'a> {
|
|||||||
.translate_gva(gva, flags.into())
|
.translate_gva(gva, flags.into())
|
||||||
.map_err(|e| PlatformError::TranslateVirtualAddress(anyhow!(e)))?;
|
.map_err(|e| PlatformError::TranslateVirtualAddress(anyhow!(e)))?;
|
||||||
|
|
||||||
|
// SAFETY: r is valid, otherwise this function will have returned
|
||||||
let result_code = unsafe { r.1.__bindgen_anon_1.result_code };
|
let result_code = unsafe { r.1.__bindgen_anon_1.result_code };
|
||||||
match result_code {
|
match result_code {
|
||||||
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => Ok(r.0),
|
hv_translate_gva_result_code_HV_TRANSLATE_GVA_SUCCESS => Ok(r.0),
|
||||||
@@ -746,6 +764,13 @@ fn hv_state_init() -> Arc<RwLock<HvState>> {
|
|||||||
/// vm.set/get().unwrap()
|
/// vm.set/get().unwrap()
|
||||||
///
|
///
|
||||||
impl vm::Vm for MshvVm {
|
impl vm::Vm for MshvVm {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
///
|
||||||
|
/// Sets the address of the one-page region in the VM's address space.
|
||||||
|
///
|
||||||
|
fn set_identity_map_address(&self, _address: u64) -> vm::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
///
|
///
|
||||||
/// Sets the address of the three-page region in the VM's address space.
|
/// Sets the address of the three-page region in the VM's address space.
|
||||||
@@ -935,6 +960,9 @@ impl vm::Vm for MshvVm {
|
|||||||
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
||||||
msi_routing[0].nr = entries.len() as u32;
|
msi_routing[0].nr = entries.len() as u32;
|
||||||
|
|
||||||
|
// SAFETY: msi_routing initialized with entries.len() and now it is being turned into
|
||||||
|
// entries_slice with entries.len() again. It is guaranteed to be large enough to hold
|
||||||
|
// everything from entries.
|
||||||
unsafe {
|
unsafe {
|
||||||
let entries_slice: &mut [mshv_msi_routing_entry] =
|
let entries_slice: &mut [mshv_msi_routing_entry] =
|
||||||
msi_routing[0].entries.as_mut_slice(entries.len());
|
msi_routing[0].entries.as_mut_slice(entries.len());
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ pub use {
|
|||||||
mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry,
|
mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry,
|
||||||
mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
||||||
mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState,
|
mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState,
|
||||||
mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
|
mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList,
|
||||||
mshv_bindings::SegmentRegister, mshv_bindings::SpecialRegisters,
|
mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs, mshv_bindings::SegmentRegister,
|
||||||
mshv_bindings::StandardRegisters, mshv_bindings::SuspendRegisters, mshv_bindings::VcpuEvents,
|
mshv_bindings::SpecialRegisters, mshv_bindings::StandardRegisters,
|
||||||
mshv_bindings::XSave as Xsave, mshv_bindings::Xcrs as ExtendedControlRegisters,
|
mshv_bindings::SuspendRegisters, mshv_bindings::VcpuEvents, mshv_bindings::XSave as Xsave,
|
||||||
|
mshv_bindings::Xcrs as ExtendedControlRegisters,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
@@ -35,6 +36,7 @@ pub struct VcpuMshvState {
|
|||||||
pub lapic: LapicState,
|
pub lapic: LapicState,
|
||||||
pub dbg: DebugRegisters,
|
pub dbg: DebugRegisters,
|
||||||
pub xsave: Xsave,
|
pub xsave: Xsave,
|
||||||
|
pub misc: MiscRegisters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for VcpuMshvState {
|
impl fmt::Display for VcpuMshvState {
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ pub enum HypervisorVmError {
|
|||||||
#[error("Failed to create Vcpu: {0}")]
|
#[error("Failed to create Vcpu: {0}")]
|
||||||
CreateVcpu(#[source] anyhow::Error),
|
CreateVcpu(#[source] anyhow::Error),
|
||||||
///
|
///
|
||||||
|
/// Identity map address error
|
||||||
|
///
|
||||||
|
#[error("Failed to set identity map address: {0}")]
|
||||||
|
SetIdentityMapAddress(#[source] anyhow::Error),
|
||||||
|
///
|
||||||
/// TSS address error
|
/// TSS address error
|
||||||
///
|
///
|
||||||
#[error("Failed to set TSS address: {0}")]
|
#[error("Failed to set TSS address: {0}")]
|
||||||
@@ -217,6 +222,9 @@ pub type Result<T> = std::result::Result<T, HypervisorVmError>;
|
|||||||
/// This crate provides a hypervisor-agnostic interfaces for Vm
|
/// This crate provides a hypervisor-agnostic interfaces for Vm
|
||||||
///
|
///
|
||||||
pub trait Vm: Send + Sync {
|
pub trait Vm: Send + Sync {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
/// Sets the address of the one-page region in the VM's address space.
|
||||||
|
fn set_identity_map_address(&self, address: u64) -> Result<()>;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
/// Sets the address of the three-page region in the VM's address space.
|
/// Sets the address of the three-page region in the VM's address space.
|
||||||
fn set_tss_address(&self, offset: usize) -> Result<()>;
|
fn set_tss_address(&self, offset: usize) -> Result<()>;
|
||||||
|
|||||||
@@ -7,19 +7,20 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
epoll = "4.3.1"
|
epoll = "4.3.1"
|
||||||
getrandom = "0.2"
|
getrandom = "0.2"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
net_gen = { path = "../net_gen" }
|
net_gen = { path = "../net_gen" }
|
||||||
rate_limiter = { path = "../rate_limiter" }
|
rate_limiter = { path = "../rate_limiter" }
|
||||||
serde = "1.0.130"
|
serde = "1.0.133"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
virtio-bindings = "0.1.0"
|
virtio-bindings = "0.1.0"
|
||||||
vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
virtio-queue = { path = "../virtio-queue" }
|
||||||
|
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||||
vm-virtio = { path = "../vm-virtio" }
|
vm-virtio = { path = "../vm-virtio" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
pnet = "0.28.0"
|
pnet = "0.29.0"
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.75"
|
||||||
|
|||||||
@@ -12,17 +12,25 @@ use virtio_bindings::bindings::virtio_net::{
|
|||||||
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
|
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
|
||||||
VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_OK,
|
VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_OK,
|
||||||
};
|
};
|
||||||
use vm_memory::{ByteValued, Bytes, GuestMemoryError};
|
use virtio_queue::Queue;
|
||||||
use vm_virtio::Queue;
|
use vm_memory::{ByteValued, Bytes, GuestMemoryAtomic, GuestMemoryError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Read queue failed.
|
/// Read queue failed.
|
||||||
GuestMemory(GuestMemoryError),
|
GuestMemory(GuestMemoryError),
|
||||||
/// No queue pairs number.
|
/// No control header descriptor
|
||||||
NoQueuePairsDescriptor,
|
NoControlHeaderDescriptor,
|
||||||
|
/// Missing the data descriptor in the chain.
|
||||||
|
NoDataDescriptor,
|
||||||
/// No status descriptor
|
/// No status descriptor
|
||||||
NoStatusDescriptor,
|
NoStatusDescriptor,
|
||||||
|
/// Failed adding used index
|
||||||
|
QueueAddUsed(virtio_queue::Error),
|
||||||
|
/// Failed creating an iterator over the queue
|
||||||
|
QueueIterator(virtio_queue::Error),
|
||||||
|
/// Failed enabling notification for the queue
|
||||||
|
QueueEnableNotification(virtio_queue::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Error>;
|
type Result<T> = std::result::Result<T, Error>;
|
||||||
@@ -34,6 +42,7 @@ pub struct ControlHeader {
|
|||||||
pub cmd: u8,
|
pub cmd: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: ControlHeader only contains a series of integers
|
||||||
unsafe impl ByteValued for ControlHeader {}
|
unsafe impl ByteValued for ControlHeader {}
|
||||||
|
|
||||||
pub struct CtrlQueue {
|
pub struct CtrlQueue {
|
||||||
@@ -45,22 +54,26 @@ impl CtrlQueue {
|
|||||||
CtrlQueue { taps }
|
CtrlQueue { taps }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process(&mut self, mem: &GuestMemoryMmap, queue: &mut Queue) -> Result<bool> {
|
pub fn process(
|
||||||
|
&mut self,
|
||||||
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
|
) -> Result<bool> {
|
||||||
let mut used_desc_heads = Vec::new();
|
let mut used_desc_heads = Vec::new();
|
||||||
for avail_desc in queue.iter(mem) {
|
for mut desc_chain in queue.iter().map_err(Error::QueueIterator)? {
|
||||||
let ctrl_hdr: ControlHeader =
|
let ctrl_desc = desc_chain.next().ok_or(Error::NoControlHeaderDescriptor)?;
|
||||||
mem.read_obj(avail_desc.addr).map_err(Error::GuestMemory)?;
|
|
||||||
let data_desc = avail_desc
|
let ctrl_hdr: ControlHeader = desc_chain
|
||||||
.next_descriptor()
|
.memory()
|
||||||
.ok_or(Error::NoQueuePairsDescriptor)?;
|
.read_obj(ctrl_desc.addr())
|
||||||
let status_desc = data_desc
|
.map_err(Error::GuestMemory)?;
|
||||||
.next_descriptor()
|
let data_desc = desc_chain.next().ok_or(Error::NoDataDescriptor)?;
|
||||||
.ok_or(Error::NoStatusDescriptor)?;
|
let status_desc = desc_chain.next().ok_or(Error::NoStatusDescriptor)?;
|
||||||
|
|
||||||
let ok = match u32::from(ctrl_hdr.class) {
|
let ok = match u32::from(ctrl_hdr.class) {
|
||||||
VIRTIO_NET_CTRL_MQ => {
|
VIRTIO_NET_CTRL_MQ => {
|
||||||
let queue_pairs = mem
|
let queue_pairs = desc_chain
|
||||||
.read_obj::<u16>(data_desc.addr)
|
.memory()
|
||||||
|
.read_obj::<u16>(data_desc.addr())
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
|
||||||
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
@@ -76,8 +89,9 @@ impl CtrlQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
|
||||||
let features = mem
|
let features = desc_chain
|
||||||
.read_obj::<u64>(data_desc.addr)
|
.memory()
|
||||||
|
.read_obj::<u64>(data_desc.addr())
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
|
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
|
||||||
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
warn!("Unsupported command: {}", ctrl_hdr.cmd);
|
||||||
@@ -102,17 +116,24 @@ impl CtrlQueue {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mem.write_obj(
|
desc_chain
|
||||||
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
|
.memory()
|
||||||
status_desc.addr,
|
.write_obj(
|
||||||
)
|
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
|
||||||
.map_err(Error::GuestMemory)?;
|
status_desc.addr(),
|
||||||
used_desc_heads.push((avail_desc.index, avail_desc.len));
|
)
|
||||||
|
.map_err(Error::GuestMemory)?;
|
||||||
|
let len = ctrl_desc.len() + data_desc.len() + status_desc.len();
|
||||||
|
used_desc_heads.push((desc_chain.head_index(), len));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (desc_index, len) in used_desc_heads.iter() {
|
for (desc_index, len) in used_desc_heads.iter() {
|
||||||
queue.add_used(mem, *desc_index, *len);
|
queue
|
||||||
queue.update_avail_event(mem);
|
.add_used(*desc_index, *len)
|
||||||
|
.map_err(Error::QueueAddUsed)?;
|
||||||
|
queue
|
||||||
|
.enable_notification()
|
||||||
|
.map_err(Error::QueueEnableNotification)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(!used_desc_heads.is_empty())
|
Ok(!used_desc_heads.is_empty())
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub struct VirtioNetConfig {
|
|||||||
pub duplex: u8,
|
pub duplex: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe because it only has data and has no implicit padding.
|
// SAFETY: it only has data and has no implicit padding.
|
||||||
unsafe impl ByteValued for VirtioNetConfig {}
|
unsafe impl ByteValued for VirtioNetConfig {}
|
||||||
|
|
||||||
/// Create a sockaddr_in from an IPv4 address, and expose it as
|
/// Create a sockaddr_in from an IPv4 address, and expose it as
|
||||||
@@ -121,7 +121,7 @@ pub fn unregister_listener(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_net_config_space(
|
pub fn build_net_config_space(
|
||||||
mut config: &mut VirtioNetConfig,
|
config: &mut VirtioNetConfig,
|
||||||
mac: MacAddr,
|
mac: MacAddr,
|
||||||
num_queues: usize,
|
num_queues: usize,
|
||||||
avail_features: &mut u64,
|
avail_features: &mut u64,
|
||||||
@@ -129,7 +129,7 @@ pub fn build_net_config_space(
|
|||||||
config.mac.copy_from_slice(mac.get_bytes());
|
config.mac.copy_from_slice(mac.get_bytes());
|
||||||
*avail_features |= 1 << VIRTIO_NET_F_MAC;
|
*avail_features |= 1 << VIRTIO_NET_F_MAC;
|
||||||
|
|
||||||
build_net_config_space_with_mq(&mut config, num_queues, avail_features);
|
build_net_config_space_with_mq(config, num_queues, avail_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_net_config_space_with_mq(
|
pub fn build_net_config_space_with_mq(
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ mod tests {
|
|||||||
|
|
||||||
let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();
|
let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();
|
||||||
|
|
||||||
println!("parsed MAC address: {}", mac.to_string());
|
println!("parsed MAC address: {}", mac);
|
||||||
|
|
||||||
let bytes = mac.get_bytes();
|
let bytes = mac.get_bytes();
|
||||||
assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
|
assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use std::num::Wrapping;
|
|||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vm_memory::{Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
|
use virtio_queue::Queue;
|
||||||
use vm_virtio::Queue;
|
use vm_memory::{Bytes, GuestMemory, GuestMemoryAtomic};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TxVirtio {
|
pub struct TxVirtio {
|
||||||
@@ -35,78 +35,101 @@ impl TxVirtio {
|
|||||||
|
|
||||||
pub fn process_desc_chain(
|
pub fn process_desc_chain(
|
||||||
&mut self,
|
&mut self,
|
||||||
mem: &GuestMemoryMmap,
|
|
||||||
tap: &mut Tap,
|
tap: &mut Tap,
|
||||||
queue: &mut Queue,
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
rate_limiter: &mut Option<RateLimiter>,
|
rate_limiter: &mut Option<RateLimiter>,
|
||||||
) -> Result<bool, NetQueuePairError> {
|
) -> Result<bool, NetQueuePairError> {
|
||||||
let mut retry_write = false;
|
let mut retry_write = false;
|
||||||
let mut rate_limit_reached = false;
|
let mut rate_limit_reached = false;
|
||||||
while let Some(avail_desc) = queue.iter(mem).next() {
|
|
||||||
if rate_limit_reached {
|
loop {
|
||||||
queue.go_to_previous_position();
|
let used_desc_head: (u16, u32);
|
||||||
|
let mut avail_iter = queue
|
||||||
|
.iter()
|
||||||
|
.map_err(NetQueuePairError::QueueIteratorFailed)?;
|
||||||
|
|
||||||
|
if let Some(mut desc_chain) = avail_iter.next() {
|
||||||
|
if rate_limit_reached {
|
||||||
|
avail_iter.go_to_previous_position();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut next_desc = desc_chain.next();
|
||||||
|
|
||||||
|
let mut iovecs = Vec::new();
|
||||||
|
while let Some(desc) = next_desc {
|
||||||
|
if !desc.is_write_only() && desc.len() > 0 {
|
||||||
|
let buf = desc_chain
|
||||||
|
.memory()
|
||||||
|
.get_slice(desc.addr(), desc.len() as usize)
|
||||||
|
.map_err(NetQueuePairError::GuestMemory)?
|
||||||
|
.as_ptr();
|
||||||
|
let iovec = libc::iovec {
|
||||||
|
iov_base: buf as *mut libc::c_void,
|
||||||
|
iov_len: desc.len() as libc::size_t,
|
||||||
|
};
|
||||||
|
iovecs.push(iovec);
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Invalid descriptor chain: address = 0x{:x} length = {} write_only = {}",
|
||||||
|
desc.addr().0,
|
||||||
|
desc.len(),
|
||||||
|
desc.is_write_only()
|
||||||
|
);
|
||||||
|
return Err(NetQueuePairError::DescriptorChainInvalid);
|
||||||
|
}
|
||||||
|
next_desc = desc_chain.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = if !iovecs.is_empty() {
|
||||||
|
let result = unsafe {
|
||||||
|
libc::writev(
|
||||||
|
tap.as_raw_fd() as libc::c_int,
|
||||||
|
iovecs.as_ptr() as *const libc::iovec,
|
||||||
|
iovecs.len() as libc::c_int,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if result < 0 {
|
||||||
|
let e = std::io::Error::last_os_error();
|
||||||
|
|
||||||
|
/* EAGAIN */
|
||||||
|
if e.kind() == std::io::ErrorKind::WouldBlock {
|
||||||
|
avail_iter.go_to_previous_position();
|
||||||
|
retry_write = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
error!("net: tx: failed writing to tap: {}", e);
|
||||||
|
return Err(NetQueuePairError::WriteTap(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
||||||
|
self.counter_frames += Wrapping(1);
|
||||||
|
|
||||||
|
result as u32
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
used_desc_head = (desc_chain.head_index(), len);
|
||||||
|
|
||||||
|
// For the sake of simplicity (similar to the RX rate limiting), we always
|
||||||
|
// let the 'last' descriptor chain go-through even if it was over the rate
|
||||||
|
// limit, and simply stop processing oncoming `avail_desc` if any.
|
||||||
|
if let Some(rate_limiter) = rate_limiter {
|
||||||
|
rate_limit_reached = !rate_limiter.consume(1, TokenType::Ops)
|
||||||
|
|| !rate_limiter.consume(len as u64, TokenType::Bytes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let head_index = avail_desc.index;
|
queue
|
||||||
let mut next_desc = Some(avail_desc);
|
.add_used(used_desc_head.0, used_desc_head.1)
|
||||||
|
.map_err(NetQueuePairError::QueueAddUsed)?;
|
||||||
let mut iovecs = Vec::new();
|
queue
|
||||||
while let Some(desc) = next_desc {
|
.enable_notification()
|
||||||
if !desc.is_write_only() && desc.len > 0 {
|
.map_err(NetQueuePairError::QueueEnableNotification)?;
|
||||||
let buf = mem
|
|
||||||
.get_slice(desc.addr, desc.len as usize)
|
|
||||||
.map_err(NetQueuePairError::GuestMemory)?
|
|
||||||
.as_ptr();
|
|
||||||
let iovec = libc::iovec {
|
|
||||||
iov_base: buf as *mut libc::c_void,
|
|
||||||
iov_len: desc.len as libc::size_t,
|
|
||||||
};
|
|
||||||
iovecs.push(iovec);
|
|
||||||
}
|
|
||||||
next_desc = desc.next_descriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
let len = if !iovecs.is_empty() {
|
|
||||||
let result = unsafe {
|
|
||||||
libc::writev(
|
|
||||||
tap.as_raw_fd() as libc::c_int,
|
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
|
||||||
iovecs.len() as libc::c_int,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if result < 0 {
|
|
||||||
let e = std::io::Error::last_os_error();
|
|
||||||
|
|
||||||
/* EAGAIN */
|
|
||||||
if e.kind() == std::io::ErrorKind::WouldBlock {
|
|
||||||
queue.go_to_previous_position();
|
|
||||||
retry_write = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
error!("net: tx: failed writing to tap: {}", e);
|
|
||||||
return Err(NetQueuePairError::WriteTap(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
|
||||||
self.counter_frames += Wrapping(1);
|
|
||||||
|
|
||||||
result as u32
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.add_used(mem, head_index, 0);
|
|
||||||
queue.update_avail_event(mem);
|
|
||||||
|
|
||||||
// For the sake of simplicity (similar to the RX rate limiting), we always
|
|
||||||
// let the 'last' descriptor chain go-through even if it was over the rate
|
|
||||||
// limit, and simply stop processing oncoming `avail_desc` if any.
|
|
||||||
if let Some(rate_limiter) = rate_limiter {
|
|
||||||
rate_limit_reached = !rate_limiter.consume(1, TokenType::Ops)
|
|
||||||
|| !rate_limiter.consume(len as u64, TokenType::Bytes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(retry_write)
|
Ok(retry_write)
|
||||||
@@ -135,87 +158,114 @@ impl RxVirtio {
|
|||||||
|
|
||||||
pub fn process_desc_chain(
|
pub fn process_desc_chain(
|
||||||
&mut self,
|
&mut self,
|
||||||
mem: &GuestMemoryMmap,
|
|
||||||
tap: &mut Tap,
|
tap: &mut Tap,
|
||||||
queue: &mut Queue,
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
rate_limiter: &mut Option<RateLimiter>,
|
rate_limiter: &mut Option<RateLimiter>,
|
||||||
) -> Result<bool, NetQueuePairError> {
|
) -> Result<bool, NetQueuePairError> {
|
||||||
let mut exhausted_descs = true;
|
let mut exhausted_descs = true;
|
||||||
let mut rate_limit_reached = false;
|
let mut rate_limit_reached = false;
|
||||||
|
|
||||||
while let Some(avail_desc) = queue.iter(mem).next() {
|
loop {
|
||||||
if rate_limit_reached {
|
let used_desc_head: (u16, u32);
|
||||||
exhausted_descs = false;
|
let mut avail_iter = queue
|
||||||
queue.go_to_previous_position();
|
.iter()
|
||||||
|
.map_err(NetQueuePairError::QueueIteratorFailed)?;
|
||||||
|
|
||||||
|
if let Some(mut desc_chain) = avail_iter.next() {
|
||||||
|
if rate_limit_reached {
|
||||||
|
exhausted_descs = false;
|
||||||
|
avail_iter.go_to_previous_position();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let desc = desc_chain
|
||||||
|
.next()
|
||||||
|
.ok_or(NetQueuePairError::DescriptorChainTooShort)?;
|
||||||
|
let num_buffers_addr = desc_chain.memory().checked_offset(desc.addr(), 10).unwrap();
|
||||||
|
let mut next_desc = Some(desc);
|
||||||
|
|
||||||
|
let mut iovecs = Vec::new();
|
||||||
|
while let Some(desc) = next_desc {
|
||||||
|
if desc.is_write_only() && desc.len() > 0 {
|
||||||
|
let buf = desc_chain
|
||||||
|
.memory()
|
||||||
|
.get_slice(desc.addr(), desc.len() as usize)
|
||||||
|
.map_err(NetQueuePairError::GuestMemory)?
|
||||||
|
.as_ptr();
|
||||||
|
let iovec = libc::iovec {
|
||||||
|
iov_base: buf as *mut libc::c_void,
|
||||||
|
iov_len: desc.len() as libc::size_t,
|
||||||
|
};
|
||||||
|
iovecs.push(iovec);
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Invalid descriptor chain: address = 0x{:x} length = {} write_only = {}",
|
||||||
|
desc.addr().0,
|
||||||
|
desc.len(),
|
||||||
|
desc.is_write_only()
|
||||||
|
);
|
||||||
|
return Err(NetQueuePairError::DescriptorChainInvalid);
|
||||||
|
}
|
||||||
|
next_desc = desc_chain.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = if !iovecs.is_empty() {
|
||||||
|
let result = unsafe {
|
||||||
|
libc::readv(
|
||||||
|
tap.as_raw_fd() as libc::c_int,
|
||||||
|
iovecs.as_ptr() as *const libc::iovec,
|
||||||
|
iovecs.len() as libc::c_int,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if result < 0 {
|
||||||
|
let e = std::io::Error::last_os_error();
|
||||||
|
exhausted_descs = false;
|
||||||
|
avail_iter.go_to_previous_position();
|
||||||
|
|
||||||
|
/* EAGAIN */
|
||||||
|
if e.kind() == std::io::ErrorKind::WouldBlock {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
error!("net: rx: failed reading from tap: {}", e);
|
||||||
|
return Err(NetQueuePairError::ReadTap(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write num_buffers to guest memory. We simply write 1 as we
|
||||||
|
// never spread the frame over more than one descriptor chain.
|
||||||
|
desc_chain
|
||||||
|
.memory()
|
||||||
|
.write_obj(1u16, num_buffers_addr)
|
||||||
|
.map_err(NetQueuePairError::GuestMemory)?;
|
||||||
|
|
||||||
|
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
||||||
|
self.counter_frames += Wrapping(1);
|
||||||
|
|
||||||
|
result as u32
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
used_desc_head = (desc_chain.head_index(), len);
|
||||||
|
|
||||||
|
// For the sake of simplicity (keeping the handling of RX_QUEUE_EVENT and
|
||||||
|
// RX_TAP_EVENT totally asynchronous), we always let the 'last' descriptor
|
||||||
|
// chain go-through even if it was over the rate limit, and simply stop
|
||||||
|
// processing oncoming `avail_desc` if any.
|
||||||
|
if let Some(rate_limiter) = rate_limiter {
|
||||||
|
rate_limit_reached = !rate_limiter.consume(1, TokenType::Ops)
|
||||||
|
|| !rate_limiter.consume(len as u64, TokenType::Bytes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let head_index = avail_desc.index;
|
queue
|
||||||
let num_buffers_addr = mem.checked_offset(avail_desc.addr, 10).unwrap();
|
.add_used(used_desc_head.0, used_desc_head.1)
|
||||||
let mut next_desc = Some(avail_desc);
|
.map_err(NetQueuePairError::QueueAddUsed)?;
|
||||||
|
queue
|
||||||
let mut iovecs = Vec::new();
|
.enable_notification()
|
||||||
while let Some(desc) = next_desc {
|
.map_err(NetQueuePairError::QueueEnableNotification)?;
|
||||||
if desc.is_write_only() && desc.len > 0 {
|
|
||||||
let buf = mem
|
|
||||||
.get_slice(desc.addr, desc.len as usize)
|
|
||||||
.map_err(NetQueuePairError::GuestMemory)?
|
|
||||||
.as_ptr();
|
|
||||||
let iovec = libc::iovec {
|
|
||||||
iov_base: buf as *mut libc::c_void,
|
|
||||||
iov_len: desc.len as libc::size_t,
|
|
||||||
};
|
|
||||||
iovecs.push(iovec);
|
|
||||||
}
|
|
||||||
next_desc = desc.next_descriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
let len = if !iovecs.is_empty() {
|
|
||||||
let result = unsafe {
|
|
||||||
libc::readv(
|
|
||||||
tap.as_raw_fd() as libc::c_int,
|
|
||||||
iovecs.as_ptr() as *const libc::iovec,
|
|
||||||
iovecs.len() as libc::c_int,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if result < 0 {
|
|
||||||
let e = std::io::Error::last_os_error();
|
|
||||||
exhausted_descs = false;
|
|
||||||
queue.go_to_previous_position();
|
|
||||||
|
|
||||||
/* EAGAIN */
|
|
||||||
if e.kind() == std::io::ErrorKind::WouldBlock {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
error!("net: rx: failed reading from tap: {}", e);
|
|
||||||
return Err(NetQueuePairError::ReadTap(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write num_buffers to guest memory. We simply write 1 as we
|
|
||||||
// never spread the frame over more than one descriptor chain.
|
|
||||||
mem.write_obj(1u16, num_buffers_addr)
|
|
||||||
.map_err(NetQueuePairError::GuestMemory)?;
|
|
||||||
|
|
||||||
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
|
||||||
self.counter_frames += Wrapping(1);
|
|
||||||
|
|
||||||
result as u32
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.add_used(mem, head_index, len);
|
|
||||||
queue.update_avail_event(mem);
|
|
||||||
|
|
||||||
// For the sake of simplicity (keeping the handling of RX_QUEUE_EVENT and
|
|
||||||
// RX_TAP_EVENT totally asynchronous), we always let the 'last' descriptor
|
|
||||||
// chain go-through even if it was over the rate limit, and simply stop
|
|
||||||
// processing oncoming `avail_desc` if any.
|
|
||||||
if let Some(rate_limiter) = rate_limiter {
|
|
||||||
rate_limit_reached = !rate_limiter.consume(1, TokenType::Ops)
|
|
||||||
|| !rate_limiter.consume(len as u64, TokenType::Bytes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(exhausted_descs)
|
Ok(exhausted_descs)
|
||||||
@@ -244,10 +294,21 @@ pub enum NetQueuePairError {
|
|||||||
ReadTap(io::Error),
|
ReadTap(io::Error),
|
||||||
/// Error related to guest memory
|
/// Error related to guest memory
|
||||||
GuestMemory(vm_memory::GuestMemoryError),
|
GuestMemory(vm_memory::GuestMemoryError),
|
||||||
|
/// Returned an error while iterating through the queue
|
||||||
|
QueueIteratorFailed(virtio_queue::Error),
|
||||||
|
/// Descriptor chain is too short
|
||||||
|
DescriptorChainTooShort,
|
||||||
|
/// Descriptor chain does not contain valid descriptors
|
||||||
|
DescriptorChainInvalid,
|
||||||
|
/// Failed to determine if queue needed notification
|
||||||
|
QueueNeedsNotification(virtio_queue::Error),
|
||||||
|
/// Failed to enable notification on the queue
|
||||||
|
QueueEnableNotification(virtio_queue::Error),
|
||||||
|
/// Failed to add used index to the queue
|
||||||
|
QueueAddUsed(virtio_queue::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NetQueuePair {
|
pub struct NetQueuePair {
|
||||||
pub mem: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
|
||||||
pub tap: Tap,
|
pub tap: Tap,
|
||||||
// With epoll each FD must be unique. So in order to filter the
|
// With epoll each FD must be unique. So in order to filter the
|
||||||
// events we need to get a second FD responding to the original
|
// events we need to get a second FD responding to the original
|
||||||
@@ -268,19 +329,13 @@ pub struct NetQueuePair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NetQueuePair {
|
impl NetQueuePair {
|
||||||
pub fn process_tx(&mut self, mut queue: &mut Queue) -> Result<bool, NetQueuePairError> {
|
pub fn process_tx(
|
||||||
let mem = self
|
&mut self,
|
||||||
.mem
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
.as_ref()
|
) -> Result<bool, NetQueuePairError> {
|
||||||
.ok_or(NetQueuePairError::NoMemoryConfigured)
|
let tx_tap_retry =
|
||||||
.map(|m| m.memory())?;
|
self.tx
|
||||||
|
.process_desc_chain(&mut self.tap, queue, &mut self.tx_rate_limiter)?;
|
||||||
let tx_tap_retry = self.tx.process_desc_chain(
|
|
||||||
&mem,
|
|
||||||
&mut self.tap,
|
|
||||||
&mut queue,
|
|
||||||
&mut self.tx_rate_limiter,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// We got told to try again when writing to the tap. Wait for the TAP to be writable
|
// We got told to try again when writing to the tap. Wait for the TAP to be writable
|
||||||
if tx_tap_retry && !self.tx_tap_listening {
|
if tx_tap_retry && !self.tx_tap_listening {
|
||||||
@@ -314,22 +369,19 @@ impl NetQueuePair {
|
|||||||
self.tx.counter_bytes = Wrapping(0);
|
self.tx.counter_bytes = Wrapping(0);
|
||||||
self.tx.counter_frames = Wrapping(0);
|
self.tx.counter_frames = Wrapping(0);
|
||||||
|
|
||||||
Ok(queue.needs_notification(&mem, queue.next_used))
|
queue
|
||||||
|
.needs_notification()
|
||||||
|
.map_err(NetQueuePairError::QueueNeedsNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_rx(&mut self, mut queue: &mut Queue) -> Result<bool, NetQueuePairError> {
|
pub fn process_rx(
|
||||||
let mem = self
|
&mut self,
|
||||||
.mem
|
queue: &mut Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||||
.as_ref()
|
) -> Result<bool, NetQueuePairError> {
|
||||||
.ok_or(NetQueuePairError::NoMemoryConfigured)
|
self.rx_desc_avail =
|
||||||
.map(|m| m.memory())?;
|
!self
|
||||||
|
.rx
|
||||||
self.rx_desc_avail = !self.rx.process_desc_chain(
|
.process_desc_chain(&mut self.tap, queue, &mut self.rx_rate_limiter)?;
|
||||||
&mem,
|
|
||||||
&mut self.tap,
|
|
||||||
&mut queue,
|
|
||||||
&mut self.rx_rate_limiter,
|
|
||||||
)?;
|
|
||||||
let rate_limit_reached = self
|
let rate_limit_reached = self
|
||||||
.rx_rate_limiter
|
.rx_rate_limiter
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -358,6 +410,8 @@ impl NetQueuePair {
|
|||||||
self.rx.counter_bytes = Wrapping(0);
|
self.rx.counter_bytes = Wrapping(0);
|
||||||
self.rx.counter_frames = Wrapping(0);
|
self.rx.counter_frames = Wrapping(0);
|
||||||
|
|
||||||
Ok(queue.needs_notification(&mem, queue.next_used))
|
queue
|
||||||
|
.needs_notification()
|
||||||
|
.map_err(NetQueuePairError::QueueNeedsNotification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,6 @@ impl Tap {
|
|||||||
ifreq.ifr_ifru.ifru_addr = addr;
|
ifreq.ifr_ifru.ifru_addr = addr;
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFADDR as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFADDR as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -230,7 +229,6 @@ impl Tap {
|
|||||||
let mut ifreq = self.get_ifreq();
|
let mut ifreq = self.get_ifreq();
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -245,7 +243,6 @@ impl Tap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFHWADDR as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFHWADDR as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -262,7 +259,6 @@ impl Tap {
|
|||||||
let ifreq = self.get_ifreq();
|
let ifreq = self.get_ifreq();
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFHWADDR as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -287,7 +283,6 @@ impl Tap {
|
|||||||
ifreq.ifr_ifru.ifru_addr = addr;
|
ifreq.ifr_ifru.ifru_addr = addr;
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFNETMASK as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFNETMASK as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -300,7 +295,6 @@ impl Tap {
|
|||||||
/// Set the offload flags for the tap interface.
|
/// Set the offload flags for the tap interface.
|
||||||
pub fn set_offload(&self, flags: c_uint) -> Result<()> {
|
pub fn set_offload(&self, flags: c_uint) -> Result<()> {
|
||||||
// ioctl is safe. Called with a valid tap fd, and we check the return.
|
// ioctl is safe. Called with a valid tap fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_val(&self.tap_file, net_gen::TUNSETOFFLOAD(), flags as c_ulong) };
|
unsafe { ioctl_with_val(&self.tap_file, net_gen::TUNSETOFFLOAD(), flags as c_ulong) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -316,7 +310,6 @@ impl Tap {
|
|||||||
|
|
||||||
let mut ifreq = self.get_ifreq();
|
let mut ifreq = self.get_ifreq();
|
||||||
|
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFFLAGS as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCGIFFLAGS as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
@@ -336,7 +329,6 @@ impl Tap {
|
|||||||
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
|
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
|
||||||
|
|
||||||
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
// ioctl is safe. Called with a valid sock fd, and we check the return.
|
||||||
#[allow(clippy::cast_lossless)]
|
|
||||||
let ret =
|
let ret =
|
||||||
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFFLAGS as c_ulong, &ifreq) };
|
unsafe { ioctl_with_ref(&sock, net_gen::sockios::SIOCSIFFLAGS as c_ulong, &ifreq) };
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::num::ParseIntError;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -37,6 +38,32 @@ impl fmt::Display for OptionParserError {
|
|||||||
}
|
}
|
||||||
type OptionParserResult<T> = std::result::Result<T, OptionParserError>;
|
type OptionParserResult<T> = std::result::Result<T, OptionParserError>;
|
||||||
|
|
||||||
|
fn split_commas_outside_brackets(s: &str) -> OptionParserResult<Vec<String>> {
|
||||||
|
let mut list: Vec<String> = Vec::new();
|
||||||
|
let mut opened_brackets: usize = 0;
|
||||||
|
for element in s.trim().split(',') {
|
||||||
|
if opened_brackets > 0 {
|
||||||
|
if let Some(last) = list.last_mut() {
|
||||||
|
*last = format!("{},{}", last, element);
|
||||||
|
} else {
|
||||||
|
return Err(OptionParserError::InvalidSyntax(s.to_owned()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.push(element.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
opened_brackets += element.matches('[').count();
|
||||||
|
let closing_brackets = element.matches(']').count();
|
||||||
|
if closing_brackets > opened_brackets {
|
||||||
|
return Err(OptionParserError::InvalidSyntax(s.to_owned()));
|
||||||
|
} else {
|
||||||
|
opened_brackets -= closing_brackets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
|
||||||
impl OptionParser {
|
impl OptionParser {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -49,9 +76,7 @@ impl OptionParser {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let options_list: Vec<&str> = input.trim().split(',').collect();
|
for option in split_commas_outside_brackets(input)?.iter() {
|
||||||
|
|
||||||
for option in options_list.iter() {
|
|
||||||
let parts: Vec<&str> = option.split('=').collect();
|
let parts: Vec<&str> = option.split('=').collect();
|
||||||
|
|
||||||
match self.options.get_mut(parts[0]) {
|
match self.options.get_mut(parts[0]) {
|
||||||
@@ -183,7 +208,11 @@ impl FromStr for IntegerList {
|
|||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
let mut integer_list = Vec::new();
|
let mut integer_list = Vec::new();
|
||||||
let ranges_list: Vec<&str> = s.trim().split(':').collect();
|
let ranges_list: Vec<&str> = s
|
||||||
|
.trim()
|
||||||
|
.trim_matches(|c| c == '[' || c == ']')
|
||||||
|
.split(',')
|
||||||
|
.collect();
|
||||||
|
|
||||||
for range in ranges_list.iter() {
|
for range in ranges_list.iter() {
|
||||||
let items: Vec<&str> = range.split('-').collect();
|
let items: Vec<&str> = range.split('-').collect();
|
||||||
@@ -216,39 +245,71 @@ impl FromStr for IntegerList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TupleTwoIntegers(pub Vec<(u64, u64)>);
|
pub trait TupleValue {
|
||||||
|
fn parse_value(input: &str) -> Result<Self, TupleError>
|
||||||
pub enum TupleTwoIntegersParseError {
|
where
|
||||||
InvalidValue(String),
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for TupleTwoIntegers {
|
impl TupleValue for u64 {
|
||||||
type Err = TupleTwoIntegersParseError;
|
fn parse_value(input: &str) -> Result<Self, TupleError> {
|
||||||
|
input.parse::<u64>().map_err(TupleError::InvalidInteger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TupleValue for Vec<u8> {
|
||||||
|
fn parse_value(input: &str) -> Result<Self, TupleError> {
|
||||||
|
Ok(IntegerList::from_str(input)
|
||||||
|
.map_err(TupleError::InvalidIntegerList)?
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|v| *v as u8)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TupleValue for Vec<u64> {
|
||||||
|
fn parse_value(input: &str) -> Result<Self, TupleError> {
|
||||||
|
Ok(IntegerList::from_str(input)
|
||||||
|
.map_err(TupleError::InvalidIntegerList)?
|
||||||
|
.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Tuple<S, T>(pub Vec<(S, T)>);
|
||||||
|
|
||||||
|
pub enum TupleError {
|
||||||
|
InvalidValue(String),
|
||||||
|
SplitOutsideBrackets(OptionParserError),
|
||||||
|
InvalidIntegerList(IntegerListParseError),
|
||||||
|
InvalidInteger(ParseIntError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: FromStr, T: TupleValue> FromStr for Tuple<S, T> {
|
||||||
|
type Err = TupleError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
let mut list = Vec::new();
|
let mut list: Vec<(S, T)> = Vec::new();
|
||||||
let tuples_list: Vec<&str> = s.trim().split(':').collect();
|
|
||||||
|
|
||||||
|
let tuples_list =
|
||||||
|
split_commas_outside_brackets(s.trim().trim_matches(|c| c == '[' || c == ']'))
|
||||||
|
.map_err(TupleError::SplitOutsideBrackets)?;
|
||||||
for tuple in tuples_list.iter() {
|
for tuple in tuples_list.iter() {
|
||||||
let items: Vec<&str> = tuple.split('@').collect();
|
let items: Vec<&str> = tuple.split('@').collect();
|
||||||
|
|
||||||
if items.len() != 2 {
|
if items.len() != 2 {
|
||||||
return Err(TupleTwoIntegersParseError::InvalidValue(
|
return Err(TupleError::InvalidValue((*tuple).to_string()));
|
||||||
(*tuple).to_string(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let item1 = items[0]
|
let item1 = items[0]
|
||||||
.parse::<u64>()
|
.parse::<S>()
|
||||||
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[0].to_owned()))?;
|
.map_err(|_| TupleError::InvalidValue(items[0].to_owned()))?;
|
||||||
let item2 = items[1]
|
let item2 = TupleValue::parse_value(items[1])?;
|
||||||
.parse::<u64>()
|
|
||||||
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[1].to_owned()))?;
|
|
||||||
|
|
||||||
list.push((item1, item2));
|
list.push((item1, item2));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TupleTwoIntegers(list))
|
Ok(Tuple(list))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +323,12 @@ impl FromStr for StringList {
|
|||||||
type Err = StringListParseError;
|
type Err = StringListParseError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
let string_list: Vec<String> = s.trim().split(':').map(|e| e.to_owned()).collect();
|
let string_list: Vec<String> = s
|
||||||
|
.trim()
|
||||||
|
.trim_matches(|c| c == '[' || c == ']')
|
||||||
|
.split(',')
|
||||||
|
.map(|e| e.to_owned())
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(StringList(string_list))
|
Ok(StringList(string_list))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,22 +10,22 @@ kvm = ["vfio-ioctls/kvm"]
|
|||||||
mshv = ["vfio-ioctls/mshv"]
|
mshv = ["vfio-ioctls/mshv"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.52"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hypervisor = { path = "../hypervisor" }
|
hypervisor = { path = "../hypervisor" }
|
||||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "main", default-features = false }
|
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "main", default-features = false }
|
||||||
vfio_user = { path = "../vfio_user" }
|
vfio_user = { path = "../vfio_user" }
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
versionize = "0.1.6"
|
versionize = "0.1.6"
|
||||||
versionize_derive = "0.1.4"
|
versionize_derive = "0.1.4"
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = "0.6.0"
|
vm-memory = "0.7.0"
|
||||||
vm-migration = { path = "../vm-migration" }
|
vm-migration = { path = "../vm-migration" }
|
||||||
|
|
||||||
[dependencies.vfio-bindings]
|
[dependencies.vfio-bindings]
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
features = ["fam-wrappers"]
|
features = ["fam-wrappers"]
|
||||||
|
|||||||
@@ -140,12 +140,8 @@ impl PciBus {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_device(
|
pub fn add_device(&mut self, device_id: u32, device: Arc<Mutex<dyn PciDevice>>) -> Result<()> {
|
||||||
&mut self,
|
self.devices.insert(device_id, device);
|
||||||
pci_device_bdf: u32,
|
|
||||||
device: Arc<Mutex<dyn PciDevice>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
self.devices.insert(pci_device_bdf >> 3, device);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -740,6 +740,11 @@ impl PciConfiguration {
|
|||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_msg_ctl(LittleEndian::read_u16(data));
|
.set_msg_ctl(LittleEndian::read_u16(data));
|
||||||
|
} else if msix_cap_reg_idx == reg_idx && offset == 0 && data.len() == 4 {
|
||||||
|
msix_config
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_msg_ctl((LittleEndian::read_u32(data) >> 16) as u16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -922,16 +927,19 @@ impl PciBarConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn set_register_index(mut self, reg_idx: usize) -> Self {
|
pub fn set_register_index(mut self, reg_idx: usize) -> Self {
|
||||||
self.reg_idx = reg_idx;
|
self.reg_idx = reg_idx;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn set_address(mut self, addr: u64) -> Self {
|
pub fn set_address(mut self, addr: u64) -> Self {
|
||||||
self.addr = addr;
|
self.addr = addr;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn set_size(mut self, size: u64) -> Self {
|
pub fn set_size(mut self, size: u64) -> Self {
|
||||||
self.size = size;
|
self.size = size;
|
||||||
self
|
self
|
||||||
@@ -941,6 +949,7 @@ impl PciBarConfiguration {
|
|||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
pub fn set_region_type(mut self, region_type: PciBarRegionType) -> Self {
|
pub fn set_region_type(mut self, region_type: PciBarRegionType) -> Self {
|
||||||
self.region_type = region_type;
|
self.region_type = region_type;
|
||||||
self
|
self
|
||||||
@@ -961,7 +970,7 @@ mod tests {
|
|||||||
foo: u8,
|
foo: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is safe to implement BytesValued; all members are simple numbers and any value is valid.
|
// SAFETY: All members are simple numbers and any value is valid.
|
||||||
unsafe impl ByteValued for TestCap {}
|
unsafe impl ByteValued for TestCap {}
|
||||||
|
|
||||||
impl PciCapability for TestCap {
|
impl PciCapability for TestCap {
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
use crate::configuration::{self, PciBarRegionType};
|
use crate::configuration::{self, PciBarRegionType};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use std::{self, io, result};
|
use std::{self, io, result};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
use vm_memory::{GuestAddress, GuestUsize};
|
use vm_memory::{GuestAddress, GuestUsize};
|
||||||
|
|
||||||
@@ -51,13 +51,18 @@ pub trait PciDevice: BusDevice {
|
|||||||
/// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples.
|
/// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples.
|
||||||
fn allocate_bars(
|
fn allocate_bars(
|
||||||
&mut self,
|
&mut self,
|
||||||
_allocator: &mut SystemAllocator,
|
_allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
|
_mmio_allocator: &mut AddressAllocator,
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>> {
|
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>> {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Frees the PCI BARs previously allocated with a call to allocate_bars().
|
/// Frees the PCI BARs previously allocated with a call to allocate_bars().
|
||||||
fn free_bars(&mut self, _allocator: &mut SystemAllocator) -> Result<()> {
|
fn free_bars(
|
||||||
|
&mut self,
|
||||||
|
_allocator: &mut SystemAllocator,
|
||||||
|
_mmio_allocator: &mut AddressAllocator,
|
||||||
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
|
|||||||
pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_TABLE_ENTRY_SIZE};
|
pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_TABLE_ENTRY_SIZE};
|
||||||
pub use self::vfio::{VfioPciDevice, VfioPciError};
|
pub use self::vfio::{VfioPciDevice, VfioPciError};
|
||||||
pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
|
pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
/// PCI has four interrupt pins A->D.
|
/// PCI has four interrupt pins A->D.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@@ -47,3 +48,76 @@ impl PciInterruptPin {
|
|||||||
pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8;
|
pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8;
|
pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub struct PciBdf(u32);
|
||||||
|
|
||||||
|
impl PciBdf {
|
||||||
|
pub fn segment(&self) -> u16 {
|
||||||
|
((self.0 >> 16) & 0xffff) as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bus(&self) -> u8 {
|
||||||
|
((self.0 >> 8) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn device(&self) -> u8 {
|
||||||
|
((self.0 >> 3) & 0x1f) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function(&self) -> u8 {
|
||||||
|
(self.0 & 0x7) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self {
|
||||||
|
Self(
|
||||||
|
(segment as u32) << 16
|
||||||
|
| (bus as u32) << 8
|
||||||
|
| ((device & 0x1f) as u32) << 3
|
||||||
|
| (function & 0x7) as u32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for PciBdf {
|
||||||
|
fn from(bdf: u32) -> Self {
|
||||||
|
Self(bdf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PciBdf> for u32 {
|
||||||
|
fn from(bdf: PciBdf) -> Self {
|
||||||
|
bdf.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&PciBdf> for u32 {
|
||||||
|
fn from(bdf: &PciBdf) -> Self {
|
||||||
|
bdf.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PciBdf> for u16 {
|
||||||
|
fn from(bdf: PciBdf) -> Self {
|
||||||
|
(bdf.0 & 0xffff) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&PciBdf> for u16 {
|
||||||
|
fn from(bdf: &PciBdf) -> Self {
|
||||||
|
(bdf.0 & 0xffff) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for PciBdf {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{:04x}:{:02x}:{:02x}.{:01x}",
|
||||||
|
self.segment(),
|
||||||
|
self.bus(),
|
||||||
|
self.device(),
|
||||||
|
self.function()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ pub struct MsixCap {
|
|||||||
pub pba: u32,
|
pub pba: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is safe to implement ByteValued. All members are simple numbers and any value is valid.
|
// SAFETY: All members are simple numbers and any value is valid.
|
||||||
unsafe impl ByteValued for MsixCap {}
|
unsafe impl ByteValued for MsixCap {}
|
||||||
|
|
||||||
impl PciCapability for MsixCap {
|
impl PciCapability for MsixCap {
|
||||||
@@ -533,4 +533,16 @@ impl MsixCap {
|
|||||||
pub fn table_size(&self) -> u16 {
|
pub fn table_size(&self) -> u16 {
|
||||||
(self.msg_ctl & 0x7ff) + 1
|
(self.msg_ctl & 0x7ff) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn table_range(&self) -> (u64, u64) {
|
||||||
|
// The table takes 16 bytes per entry.
|
||||||
|
let size = self.table_size() as u64 * 16;
|
||||||
|
(self.table_offset() as u64, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pba_range(&self) -> (u64, u64) {
|
||||||
|
// The table takes 1 bit per entry modulo 8 bytes.
|
||||||
|
let size = ((self.table_size() as u64 / 64) + 1) * 8;
|
||||||
|
(self.pba_offset() as u64, size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
311
pci/src/vfio.rs
311
pci/src/vfio.rs
@@ -5,20 +5,21 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
msi_num_enabled_vectors, BarReprogrammingParams, MsiConfig, MsixCap, MsixConfig,
|
msi_num_enabled_vectors, BarReprogrammingParams, MsiConfig, MsixCap, MsixConfig,
|
||||||
PciBarConfiguration, PciBarRegionType, PciCapabilityId, PciClassCode, PciConfiguration,
|
PciBarConfiguration, PciBarRegionType, PciBdf, PciCapabilityId, PciClassCode, PciConfiguration,
|
||||||
PciDevice, PciDeviceError, PciHeaderType, PciSubclass, MSIX_TABLE_ENTRY_SIZE,
|
PciDevice, PciDeviceError, PciHeaderType, PciSubclass, MSIX_TABLE_ENTRY_SIZE,
|
||||||
};
|
};
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use hypervisor::HypervisorVmError;
|
use hypervisor::HypervisorVmError;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
use std::sync::{Arc, Barrier};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vfio_bindings::bindings::vfio::*;
|
use vfio_bindings::bindings::vfio::*;
|
||||||
use vfio_ioctls::{VfioContainer, VfioDevice, VfioIrq};
|
use vfio_ioctls::{VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::interrupt::{
|
use vm_device::interrupt::{
|
||||||
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
||||||
};
|
};
|
||||||
@@ -209,6 +210,14 @@ impl Interrupt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct UserMemoryRegion {
|
||||||
|
slot: u32,
|
||||||
|
start: u64,
|
||||||
|
size: u64,
|
||||||
|
host_addr: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct MmioRegion {
|
pub struct MmioRegion {
|
||||||
pub start: GuestAddress,
|
pub start: GuestAddress,
|
||||||
pub length: GuestUsize,
|
pub length: GuestUsize,
|
||||||
@@ -217,6 +226,7 @@ pub struct MmioRegion {
|
|||||||
pub(crate) mem_slot: Option<u32>,
|
pub(crate) mem_slot: Option<u32>,
|
||||||
pub(crate) host_addr: Option<u64>,
|
pub(crate) host_addr: Option<u64>,
|
||||||
pub(crate) mmap_size: Option<usize>,
|
pub(crate) mmap_size: Option<usize>,
|
||||||
|
pub(crate) user_memory_regions: Vec<UserMemoryRegion>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum VfioError {
|
pub enum VfioError {
|
||||||
@@ -350,7 +360,8 @@ pub(crate) struct VfioCommon {
|
|||||||
impl VfioCommon {
|
impl VfioCommon {
|
||||||
pub(crate) fn allocate_bars(
|
pub(crate) fn allocate_bars(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocator: &mut SystemAllocator,
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
vfio_wrapper: &dyn Vfio,
|
vfio_wrapper: &dyn Vfio,
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
||||||
let mut ranges = Vec::new();
|
let mut ranges = Vec::new();
|
||||||
@@ -400,25 +411,27 @@ impl VfioCommon {
|
|||||||
let mut lower = vfio_wrapper.read_config_dword(bar_offset);
|
let mut lower = vfio_wrapper.read_config_dword(bar_offset);
|
||||||
|
|
||||||
if io_bar {
|
if io_bar {
|
||||||
|
// Mask flag bits (lowest 2 for I/O bars)
|
||||||
|
lower &= !0b11;
|
||||||
|
|
||||||
|
// BAR is not enabled
|
||||||
|
if lower == 0 {
|
||||||
|
bar_id += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
{
|
{
|
||||||
// IO BAR
|
// IO BAR
|
||||||
region_type = PciBarRegionType::IoRegion;
|
region_type = PciBarRegionType::IoRegion;
|
||||||
|
|
||||||
// Mask flag bits (lowest 2 for I/O bars)
|
|
||||||
lower &= !0b11;
|
|
||||||
|
|
||||||
// BAR is not enabled
|
|
||||||
if lower == 0 {
|
|
||||||
bar_id += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert bits and add 1 to calculate size
|
// Invert bits and add 1 to calculate size
|
||||||
region_size = (!lower + 1) as u64;
|
region_size = (!lower + 1) as u64;
|
||||||
|
|
||||||
// The address needs to be 4 bytes aligned.
|
// The address needs to be 4 bytes aligned.
|
||||||
bar_addr = allocator
|
bar_addr = allocator
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
.allocate_io_addresses(None, region_size, Some(0x4))
|
.allocate_io_addresses(None, region_size, Some(0x4))
|
||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
||||||
}
|
}
|
||||||
@@ -448,8 +461,8 @@ impl VfioCommon {
|
|||||||
region_size = (!combined_size + 1) as u64;
|
region_size = (!combined_size + 1) as u64;
|
||||||
|
|
||||||
// BAR allocation must be naturally aligned
|
// BAR allocation must be naturally aligned
|
||||||
bar_addr = allocator
|
bar_addr = mmio_allocator
|
||||||
.allocate_mmio_addresses(None, region_size, Some(region_size))
|
.allocate(None, region_size, Some(region_size))
|
||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
||||||
} else {
|
} else {
|
||||||
// Mask out flag bits (lowest 4 for memory bars)
|
// Mask out flag bits (lowest 4 for memory bars)
|
||||||
@@ -465,6 +478,8 @@ impl VfioCommon {
|
|||||||
|
|
||||||
// BAR allocation must be naturally aligned
|
// BAR allocation must be naturally aligned
|
||||||
bar_addr = allocator
|
bar_addr = allocator
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
.allocate_mmio_hole_addresses(None, region_size, Some(region_size))
|
.allocate_mmio_hole_addresses(None, region_size, Some(region_size))
|
||||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
|
||||||
}
|
}
|
||||||
@@ -501,6 +516,7 @@ impl VfioCommon {
|
|||||||
mem_slot: None,
|
mem_slot: None,
|
||||||
host_addr: None,
|
host_addr: None,
|
||||||
mmap_size: None,
|
mmap_size: None,
|
||||||
|
user_memory_regions: Vec::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
bar_id += 1;
|
bar_id += 1;
|
||||||
@@ -515,6 +531,7 @@ impl VfioCommon {
|
|||||||
pub(crate) fn free_bars(
|
pub(crate) fn free_bars(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocator: &mut SystemAllocator,
|
allocator: &mut SystemAllocator,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
) -> Result<(), PciDeviceError> {
|
) -> Result<(), PciDeviceError> {
|
||||||
for region in self.mmio_regions.iter() {
|
for region in self.mmio_regions.iter() {
|
||||||
match region.type_ {
|
match region.type_ {
|
||||||
@@ -528,7 +545,7 @@ impl VfioCommon {
|
|||||||
allocator.free_mmio_hole_addresses(region.start, region.length);
|
allocator.free_mmio_hole_addresses(region.start, region.length);
|
||||||
}
|
}
|
||||||
PciBarRegionType::Memory64BitRegion => {
|
PciBarRegionType::Memory64BitRegion => {
|
||||||
allocator.free_mmio_addresses(region.start, region.length);
|
mmio_allocator.free(region.start, region.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,6 +557,7 @@ impl VfioCommon {
|
|||||||
cap: u8,
|
cap: u8,
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
vfio_wrapper: &dyn Vfio,
|
vfio_wrapper: &dyn Vfio,
|
||||||
|
bdf: PciBdf,
|
||||||
) {
|
) {
|
||||||
let msg_ctl = vfio_wrapper.read_config_word((cap + 2).into());
|
let msg_ctl = vfio_wrapper.read_config_word((cap + 2).into());
|
||||||
|
|
||||||
@@ -560,7 +578,11 @@ impl VfioCommon {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let msix_config = MsixConfig::new(msix_cap.table_size(), interrupt_source_group.clone(), 0);
|
let msix_config = MsixConfig::new(
|
||||||
|
msix_cap.table_size(),
|
||||||
|
interrupt_source_group.clone(),
|
||||||
|
bdf.into(),
|
||||||
|
);
|
||||||
|
|
||||||
self.interrupt.msix = Some(VfioMsix {
|
self.interrupt.msix = Some(VfioMsix {
|
||||||
bar: msix_config,
|
bar: msix_config,
|
||||||
@@ -598,6 +620,7 @@ impl VfioCommon {
|
|||||||
&mut self,
|
&mut self,
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
vfio_wrapper: &dyn Vfio,
|
vfio_wrapper: &dyn Vfio,
|
||||||
|
bdf: PciBdf,
|
||||||
) {
|
) {
|
||||||
let mut cap_next = vfio_wrapper.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
|
let mut cap_next = vfio_wrapper.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
|
||||||
|
|
||||||
@@ -619,7 +642,12 @@ impl VfioCommon {
|
|||||||
if irq_info.count > 0 {
|
if irq_info.count > 0 {
|
||||||
// Parse capability only if the VFIO device
|
// Parse capability only if the VFIO device
|
||||||
// supports MSI-X.
|
// supports MSI-X.
|
||||||
self.parse_msix_capabilities(cap_next, interrupt_manager, vfio_wrapper);
|
self.parse_msix_capabilities(
|
||||||
|
cap_next,
|
||||||
|
interrupt_manager,
|
||||||
|
vfio_wrapper,
|
||||||
|
bdf,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -786,7 +814,7 @@ impl VfioCommon {
|
|||||||
if addr >= region.start.raw_value()
|
if addr >= region.start.raw_value()
|
||||||
&& addr < region.start.unchecked_add(region.length).raw_value()
|
&& addr < region.start.unchecked_add(region.length).raw_value()
|
||||||
{
|
{
|
||||||
return Some(*region);
|
return Some(region.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -951,6 +979,7 @@ impl VfioPciDevice {
|
|||||||
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
||||||
iommu_attached: bool,
|
iommu_attached: bool,
|
||||||
|
bdf: PciBdf,
|
||||||
) -> Result<Self, VfioPciError> {
|
) -> Result<Self, VfioPciError> {
|
||||||
let device = Arc::new(device);
|
let device = Arc::new(device);
|
||||||
device.reset();
|
device.reset();
|
||||||
@@ -980,7 +1009,7 @@ impl VfioPciDevice {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper);
|
common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper, bdf);
|
||||||
common.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)?;
|
common.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)?;
|
||||||
|
|
||||||
let vfio_pci_device = VfioPciDevice {
|
let vfio_pci_device = VfioPciDevice {
|
||||||
@@ -999,6 +1028,85 @@ 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_user_memory_regions<F>(
|
||||||
|
region_index: u32,
|
||||||
|
region_start: u64,
|
||||||
|
region_size: u64,
|
||||||
|
host_addr: u64,
|
||||||
|
mem_slot: F,
|
||||||
|
vfio_msix: Option<&VfioMsix>,
|
||||||
|
) -> Vec<UserMemoryRegion>
|
||||||
|
where
|
||||||
|
F: Fn() -> u32,
|
||||||
|
{
|
||||||
|
if !Self::is_4k_aligned(region_start) {
|
||||||
|
error!(
|
||||||
|
"Region start address 0x{:x} must be at least aligned on 4KiB",
|
||||||
|
region_start
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if !Self::is_4k_multiple(region_size) {
|
||||||
|
error!(
|
||||||
|
"Region size 0x{:x} must be at least a multiple of 4KiB",
|
||||||
|
region_size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a BtreeMap as the list provided through the iterator is sorted
|
||||||
|
// by key. This ensures proper split of the whole region.
|
||||||
|
let mut inter_ranges = BTreeMap::new();
|
||||||
|
if let Some(msix) = vfio_msix {
|
||||||
|
if region_index == msix.cap.table_bir() {
|
||||||
|
let (offset, size) = msix.cap.table_range();
|
||||||
|
let base = region_start + offset;
|
||||||
|
inter_ranges.insert(base, size);
|
||||||
|
}
|
||||||
|
if region_index == msix.cap.pba_bir() {
|
||||||
|
let (offset, size) = msix.cap.pba_range();
|
||||||
|
let base = region_start + offset;
|
||||||
|
inter_ranges.insert(base, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut user_memory_regions = Vec::new();
|
||||||
|
let mut new_start = region_start;
|
||||||
|
for (range_start, range_size) in inter_ranges {
|
||||||
|
if range_start > new_start {
|
||||||
|
user_memory_regions.push(UserMemoryRegion {
|
||||||
|
slot: mem_slot(),
|
||||||
|
start: new_start,
|
||||||
|
size: range_start - new_start,
|
||||||
|
host_addr: host_addr + new_start - region_start,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
new_start = Self::align_4k(range_start + range_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if region_start + region_size > new_start {
|
||||||
|
user_memory_regions.push(UserMemoryRegion {
|
||||||
|
slot: mem_slot(),
|
||||||
|
start: new_start,
|
||||||
|
size: region_start + region_size - new_start,
|
||||||
|
host_addr: host_addr + new_start - region_start,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
user_memory_regions
|
||||||
|
}
|
||||||
|
|
||||||
/// Map MMIO regions into the guest, and avoid VM exits when the guest tries
|
/// Map MMIO regions into the guest, and avoid VM exits when the guest tries
|
||||||
/// to reach those regions.
|
/// to reach those regions.
|
||||||
///
|
///
|
||||||
@@ -1018,16 +1126,6 @@ impl VfioPciDevice {
|
|||||||
let fd = self.device.as_raw_fd();
|
let fd = self.device.as_raw_fd();
|
||||||
|
|
||||||
for region in self.common.mmio_regions.iter_mut() {
|
for region in self.common.mmio_regions.iter_mut() {
|
||||||
// We want to skip the mapping of the BAR containing the MSI-X
|
|
||||||
// table even if it is mappable. The reason is we need to trap
|
|
||||||
// any access to the MSI-X table and update the GSI routing
|
|
||||||
// accordingly.
|
|
||||||
if let Some(msix) = &self.common.interrupt.msix {
|
|
||||||
if region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let region_flags = self.device.get_region_flags(region.index);
|
let region_flags = self.device.get_region_flags(region.index);
|
||||||
if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
|
if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
|
||||||
let mut prot = 0;
|
let mut prot = 0;
|
||||||
@@ -1037,8 +1135,27 @@ impl VfioPciDevice {
|
|||||||
if region_flags & VFIO_REGION_INFO_FLAG_WRITE != 0 {
|
if region_flags & VFIO_REGION_INFO_FLAG_WRITE != 0 {
|
||||||
prot |= libc::PROT_WRITE;
|
prot |= libc::PROT_WRITE;
|
||||||
}
|
}
|
||||||
let (mmap_offset, mmap_size) = self.device.get_region_mmap(region.index);
|
|
||||||
let offset = self.device.get_region_offset(region.index) + mmap_offset;
|
// Retrieve the list of capabilities found on the region
|
||||||
|
let caps = if region_flags & VFIO_REGION_INFO_FLAG_CAPS != 0 {
|
||||||
|
self.device.get_region_caps(region.index)
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't try to mmap the region if it contains MSI-X table or
|
||||||
|
// MSI-X PBA subregion, and if we couldn't find MSIX_MAPPABLE
|
||||||
|
// in the list of supported capabilities.
|
||||||
|
if let Some(msix) = self.common.interrupt.msix.as_ref() {
|
||||||
|
if (region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir())
|
||||||
|
&& !caps.contains(&VfioRegionInfoCap::MsixMappable)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mmap_size = self.device.get_region_size(region.index);
|
||||||
|
let offset = self.device.get_region_offset(region.index);
|
||||||
|
|
||||||
let host_addr = unsafe {
|
let host_addr = unsafe {
|
||||||
libc::mmap(
|
libc::mmap(
|
||||||
@@ -1053,29 +1170,44 @@ impl VfioPciDevice {
|
|||||||
|
|
||||||
if host_addr == libc::MAP_FAILED {
|
if host_addr == libc::MAP_FAILED {
|
||||||
error!(
|
error!(
|
||||||
"Could not mmap regions, error:{}",
|
"Could not mmap region index {}: {}",
|
||||||
|
region.index,
|
||||||
io::Error::last_os_error()
|
io::Error::last_os_error()
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let slot = mem_slot();
|
// In case the region that is being mapped contains the MSI-X
|
||||||
let mem_region = vm.make_user_memory_region(
|
// vectors table or the MSI-X PBA table, we must adjust what
|
||||||
slot,
|
// is being declared through the hypervisor. We want to make
|
||||||
region.start.raw_value() + mmap_offset,
|
// sure we will still trap MMIO accesses to these MSI-X
|
||||||
mmap_size as u64,
|
// specific ranges.
|
||||||
|
let user_memory_regions = Self::generate_user_memory_regions(
|
||||||
|
region.index,
|
||||||
|
region.start.raw_value(),
|
||||||
|
mmap_size,
|
||||||
host_addr as u64,
|
host_addr as u64,
|
||||||
false,
|
&mem_slot,
|
||||||
false,
|
self.common.interrupt.msix.as_ref(),
|
||||||
);
|
);
|
||||||
|
for user_memory_region in user_memory_regions.iter() {
|
||||||
|
let mem_region = vm.make_user_memory_region(
|
||||||
|
user_memory_region.slot,
|
||||||
|
user_memory_region.start,
|
||||||
|
user_memory_region.size,
|
||||||
|
user_memory_region.host_addr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
vm.create_user_memory_region(mem_region)
|
vm.create_user_memory_region(mem_region)
|
||||||
.map_err(VfioPciError::MapRegionGuest)?;
|
.map_err(VfioPciError::MapRegionGuest)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the region with memory mapped info.
|
// Update the region with memory mapped info.
|
||||||
region.mem_slot = Some(slot);
|
|
||||||
region.host_addr = Some(host_addr as u64);
|
region.host_addr = Some(host_addr as u64);
|
||||||
region.mmap_size = Some(mmap_size as usize);
|
region.mmap_size = Some(mmap_size as usize);
|
||||||
|
region.user_memory_regions = user_memory_regions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,17 +1216,13 @@ impl VfioPciDevice {
|
|||||||
|
|
||||||
pub fn unmap_mmio_regions(&mut self) {
|
pub fn unmap_mmio_regions(&mut self) {
|
||||||
for region in self.common.mmio_regions.iter() {
|
for region in self.common.mmio_regions.iter() {
|
||||||
if let (Some(host_addr), Some(mmap_size), Some(mem_slot)) =
|
for user_memory_region in region.user_memory_regions.iter() {
|
||||||
(region.host_addr, region.mmap_size, region.mem_slot)
|
|
||||||
{
|
|
||||||
let (mmap_offset, _) = self.device.get_region_mmap(region.index);
|
|
||||||
|
|
||||||
// Remove region
|
// Remove region
|
||||||
let r = self.vm.make_user_memory_region(
|
let r = self.vm.make_user_memory_region(
|
||||||
mem_slot,
|
user_memory_region.slot,
|
||||||
region.start.raw_value() + mmap_offset,
|
user_memory_region.start,
|
||||||
mmap_size as u64,
|
user_memory_region.size,
|
||||||
host_addr as u64,
|
user_memory_region.host_addr,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
@@ -1102,7 +1230,9 @@ impl VfioPciDevice {
|
|||||||
if let Err(e) = self.vm.remove_user_memory_region(r) {
|
if let Err(e) = self.vm.remove_user_memory_region(r) {
|
||||||
error!("Could not remove the userspace memory region: {}", e);
|
error!("Could not remove the userspace memory region: {}", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (Some(host_addr), Some(mmap_size)) = (region.host_addr, region.mmap_size) {
|
||||||
let ret = unsafe { libc::munmap(host_addr as *mut libc::c_void, mmap_size) };
|
let ret = unsafe { libc::munmap(host_addr as *mut libc::c_void, mmap_size) };
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
error!(
|
error!(
|
||||||
@@ -1194,13 +1324,19 @@ const PCI_ROM_EXP_BAR_INDEX: usize = 12;
|
|||||||
impl PciDevice for VfioPciDevice {
|
impl PciDevice for VfioPciDevice {
|
||||||
fn allocate_bars(
|
fn allocate_bars(
|
||||||
&mut self,
|
&mut self,
|
||||||
allocator: &mut SystemAllocator,
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
||||||
self.common.allocate_bars(allocator, &self.vfio_wrapper)
|
self.common
|
||||||
|
.allocate_bars(allocator, mmio_allocator, &self.vfio_wrapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_bars(&mut self, allocator: &mut SystemAllocator) -> Result<(), PciDeviceError> {
|
fn free_bars(
|
||||||
self.common.free_bars(allocator)
|
&mut self,
|
||||||
|
allocator: &mut SystemAllocator,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
|
) -> Result<(), PciDeviceError> {
|
||||||
|
self.common.free_bars(allocator, mmio_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_config_register(
|
fn write_config_register(
|
||||||
@@ -1242,38 +1378,41 @@ impl PciDevice for VfioPciDevice {
|
|||||||
if region.start.raw_value() == old_base {
|
if region.start.raw_value() == old_base {
|
||||||
region.start = GuestAddress(new_base);
|
region.start = GuestAddress(new_base);
|
||||||
|
|
||||||
if let Some(mem_slot) = region.mem_slot {
|
for user_memory_region in region.user_memory_regions.iter_mut() {
|
||||||
if let Some(host_addr) = region.host_addr {
|
// Remove old region
|
||||||
let (mmap_offset, mmap_size) = self.device.get_region_mmap(region.index);
|
let old_mem_region = self.vm.make_user_memory_region(
|
||||||
|
user_memory_region.slot,
|
||||||
|
user_memory_region.start,
|
||||||
|
user_memory_region.size,
|
||||||
|
user_memory_region.host_addr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
// Remove old region
|
self.vm
|
||||||
let old_mem_region = self.vm.make_user_memory_region(
|
.remove_user_memory_region(old_mem_region)
|
||||||
mem_slot,
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
old_base + mmap_offset,
|
|
||||||
mmap_size as u64,
|
|
||||||
host_addr as u64,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
// Update the user memory region with the correct start address.
|
||||||
.remove_user_memory_region(old_mem_region)
|
if new_base > old_base {
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
user_memory_region.start += new_base - old_base;
|
||||||
|
} else {
|
||||||
// Insert new region
|
user_memory_region.start -= old_base - new_base;
|
||||||
let new_mem_region = self.vm.make_user_memory_region(
|
|
||||||
mem_slot,
|
|
||||||
new_base + mmap_offset,
|
|
||||||
mmap_size as u64,
|
|
||||||
host_addr as u64,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
|
||||||
.create_user_memory_region(new_mem_region)
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert new region
|
||||||
|
let new_mem_region = self.vm.make_user_memory_region(
|
||||||
|
user_memory_region.slot,
|
||||||
|
user_memory_region.start,
|
||||||
|
user_memory_region.size,
|
||||||
|
user_memory_region.host_addr,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.vm
|
||||||
|
.create_user_memory_region(new_mem_region)
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
use crate::vfio::{Interrupt, Vfio, VfioCommon, VfioError};
|
use crate::vfio::{Interrupt, Vfio, VfioCommon, VfioError};
|
||||||
use crate::{BarReprogrammingParams, PciBarRegionType, VfioPciError};
|
use crate::{BarReprogrammingParams, PciBarRegionType, VfioPciError};
|
||||||
use crate::{
|
use crate::{
|
||||||
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
PciBdf, PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
||||||
};
|
};
|
||||||
use hypervisor::HypervisorVmError;
|
use hypervisor::HypervisorVmError;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@@ -18,7 +18,7 @@ use thiserror::Error;
|
|||||||
use vfio_bindings::bindings::vfio::*;
|
use vfio_bindings::bindings::vfio::*;
|
||||||
use vfio_ioctls::VfioIrq;
|
use vfio_ioctls::VfioIrq;
|
||||||
use vfio_user::{Client, Error as VfioUserError};
|
use vfio_user::{Client, Error as VfioUserError};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||||
use vm_device::interrupt::{InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig};
|
use vm_device::interrupt::{InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig};
|
||||||
use vm_device::BusDevice;
|
use vm_device::BusDevice;
|
||||||
@@ -67,6 +67,7 @@ impl VfioUserPciDevice {
|
|||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
||||||
|
bdf: PciBdf,
|
||||||
) -> Result<Self, VfioUserPciDeviceError> {
|
) -> Result<Self, VfioUserPciDeviceError> {
|
||||||
// This is used for the BAR and capabilities only
|
// This is used for the BAR and capabilities only
|
||||||
let configuration = PciConfiguration::new(
|
let configuration = PciConfiguration::new(
|
||||||
@@ -104,7 +105,7 @@ impl VfioUserPciDevice {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper);
|
common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper, bdf);
|
||||||
common
|
common
|
||||||
.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)
|
.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)
|
||||||
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
||||||
@@ -116,215 +117,7 @@ impl VfioUserPciDevice {
|
|||||||
common,
|
common,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BusDevice for VfioUserPciDevice {
|
|
||||||
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>> {
|
|
||||||
self.write_bar(base, offset, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u32)]
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
enum Regions {
|
|
||||||
Bar0,
|
|
||||||
Bar1,
|
|
||||||
Bar2,
|
|
||||||
Bar3,
|
|
||||||
Bar4,
|
|
||||||
Bar5,
|
|
||||||
Rom,
|
|
||||||
Config,
|
|
||||||
Vga,
|
|
||||||
Migration,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VfioUserClientWrapper {
|
|
||||||
client: Arc<Mutex<Client>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vfio for VfioUserClientWrapper {
|
|
||||||
fn region_read(&self, index: u32, offset: u64, data: &mut [u8]) {
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.region_read(index, offset, data)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn region_write(&self, index: u32, offset: u64, data: &[u8]) {
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.region_write(index, offset, data)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_irq_info(&self, irq_index: u32) -> Option<VfioIrq> {
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_irq_info(irq_index)
|
|
||||||
.ok()
|
|
||||||
.map(|i| VfioIrq {
|
|
||||||
index: i.index,
|
|
||||||
flags: i.flags,
|
|
||||||
count: i.count,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enable_irq(&self, irq_index: u32, event_fds: Vec<&EventFd>) -> Result<(), VfioError> {
|
|
||||||
info!(
|
|
||||||
"Enabling IRQ {:x} number of fds = {:?}",
|
|
||||||
irq_index,
|
|
||||||
event_fds.len()
|
|
||||||
);
|
|
||||||
let fds: Vec<i32> = event_fds.iter().map(|e| e.as_raw_fd()).collect();
|
|
||||||
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.set_irqs(
|
|
||||||
irq_index,
|
|
||||||
VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
|
|
||||||
0,
|
|
||||||
event_fds.len() as u32,
|
|
||||||
&fds,
|
|
||||||
)
|
|
||||||
.map_err(VfioError::VfioUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disable_irq(&self, irq_index: u32) -> Result<(), VfioError> {
|
|
||||||
info!("Disabling IRQ {:x}", irq_index);
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.set_irqs(
|
|
||||||
irq_index,
|
|
||||||
VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.map_err(VfioError::VfioUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unmask_irq(&self, irq_index: u32) -> Result<(), VfioError> {
|
|
||||||
info!("Unmasking IRQ {:x}", irq_index);
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.set_irqs(
|
|
||||||
irq_index,
|
|
||||||
VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.map_err(VfioError::VfioUser)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PciDevice for VfioUserPciDevice {
|
|
||||||
fn allocate_bars(
|
|
||||||
&mut self,
|
|
||||||
allocator: &mut SystemAllocator,
|
|
||||||
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
|
||||||
self.common.allocate_bars(allocator, &self.vfio_wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn free_bars(&mut self, allocator: &mut SystemAllocator) -> Result<(), PciDeviceError> {
|
|
||||||
self.common.free_bars(allocator)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn detect_bar_reprogramming(
|
|
||||||
&mut self,
|
|
||||||
reg_idx: usize,
|
|
||||||
data: &[u8],
|
|
||||||
) -> Option<BarReprogrammingParams> {
|
|
||||||
self.common
|
|
||||||
.configuration
|
|
||||||
.detect_bar_reprogramming(reg_idx, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_config_register(
|
|
||||||
&mut self,
|
|
||||||
reg_idx: usize,
|
|
||||||
offset: u64,
|
|
||||||
data: &[u8],
|
|
||||||
) -> Option<Arc<Barrier>> {
|
|
||||||
self.common
|
|
||||||
.write_config_register(reg_idx, offset, data, &self.vfio_wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
|
|
||||||
self.common
|
|
||||||
.read_config_register(reg_idx, &self.vfio_wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_bar(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
|
||||||
self.common.read_bar(base, offset, data, &self.vfio_wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_bar(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
|
||||||
self.common
|
|
||||||
.write_bar(base, offset, data, &self.vfio_wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn move_bar(&mut self, old_base: u64, new_base: u64) -> Result<(), std::io::Error> {
|
|
||||||
info!("Moving BAR 0x{:x} -> 0x{:x}", old_base, new_base);
|
|
||||||
for mmio_region in self.common.mmio_regions.iter_mut() {
|
|
||||||
if mmio_region.start.raw_value() == old_base {
|
|
||||||
mmio_region.start = GuestAddress(new_base);
|
|
||||||
|
|
||||||
if let Some(mem_slot) = mmio_region.mem_slot {
|
|
||||||
if let Some(host_addr) = mmio_region.host_addr {
|
|
||||||
// Remove original region
|
|
||||||
let old_region = self.vm.make_user_memory_region(
|
|
||||||
mem_slot,
|
|
||||||
old_base,
|
|
||||||
mmio_region.length as u64,
|
|
||||||
host_addr as u64,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
|
||||||
.remove_user_memory_region(old_region)
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
|
||||||
|
|
||||||
let new_region = self.vm.make_user_memory_region(
|
|
||||||
mem_slot,
|
|
||||||
new_base,
|
|
||||||
mmio_region.length as u64,
|
|
||||||
host_addr as u64,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.vm
|
|
||||||
.create_user_memory_region(new_region)
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info!("Moved bar 0x{:x} -> 0x{:x}", old_base, new_base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VfioUserPciDevice {
|
|
||||||
pub fn map_mmio_regions<F>(
|
pub fn map_mmio_regions<F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
@@ -466,6 +259,234 @@ impl VfioUserPciDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BusDevice for VfioUserPciDevice {
|
||||||
|
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>> {
|
||||||
|
self.write_bar(base, offset, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
enum Regions {
|
||||||
|
Bar0,
|
||||||
|
Bar1,
|
||||||
|
Bar2,
|
||||||
|
Bar3,
|
||||||
|
Bar4,
|
||||||
|
Bar5,
|
||||||
|
Rom,
|
||||||
|
Config,
|
||||||
|
Vga,
|
||||||
|
Migration,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VfioUserClientWrapper {
|
||||||
|
client: Arc<Mutex<Client>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vfio for VfioUserClientWrapper {
|
||||||
|
fn region_read(&self, index: u32, offset: u64, data: &mut [u8]) {
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.region_read(index, offset, data)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn region_write(&self, index: u32, offset: u64, data: &[u8]) {
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.region_write(index, offset, data)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_irq_info(&self, irq_index: u32) -> Option<VfioIrq> {
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get_irq_info(irq_index)
|
||||||
|
.ok()
|
||||||
|
.map(|i| VfioIrq {
|
||||||
|
index: i.index,
|
||||||
|
flags: i.flags,
|
||||||
|
count: i.count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable_irq(&self, irq_index: u32, event_fds: Vec<&EventFd>) -> Result<(), VfioError> {
|
||||||
|
info!(
|
||||||
|
"Enabling IRQ {:x} number of fds = {:?}",
|
||||||
|
irq_index,
|
||||||
|
event_fds.len()
|
||||||
|
);
|
||||||
|
let fds: Vec<i32> = event_fds.iter().map(|e| e.as_raw_fd()).collect();
|
||||||
|
|
||||||
|
// Batch into blocks of 16 fds as sendmsg() has a size limit
|
||||||
|
let mut sent_fds = 0;
|
||||||
|
let num_fds = event_fds.len() as u32;
|
||||||
|
while sent_fds < num_fds {
|
||||||
|
let remaining_fds = num_fds - sent_fds;
|
||||||
|
let count = if remaining_fds > 16 {
|
||||||
|
16
|
||||||
|
} else {
|
||||||
|
remaining_fds
|
||||||
|
};
|
||||||
|
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_irqs(
|
||||||
|
irq_index,
|
||||||
|
VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
|
||||||
|
sent_fds,
|
||||||
|
count,
|
||||||
|
&fds[sent_fds as usize..(sent_fds + count) as usize],
|
||||||
|
)
|
||||||
|
.map_err(VfioError::VfioUser)?;
|
||||||
|
|
||||||
|
sent_fds += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disable_irq(&self, irq_index: u32) -> Result<(), VfioError> {
|
||||||
|
info!("Disabling IRQ {:x}", irq_index);
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_irqs(
|
||||||
|
irq_index,
|
||||||
|
VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.map_err(VfioError::VfioUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmask_irq(&self, irq_index: u32) -> Result<(), VfioError> {
|
||||||
|
info!("Unmasking IRQ {:x}", irq_index);
|
||||||
|
self.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_irqs(
|
||||||
|
irq_index,
|
||||||
|
VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.map_err(VfioError::VfioUser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PciDevice for VfioUserPciDevice {
|
||||||
|
fn allocate_bars(
|
||||||
|
&mut self,
|
||||||
|
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
|
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>, PciDeviceError> {
|
||||||
|
self.common
|
||||||
|
.allocate_bars(allocator, mmio_allocator, &self.vfio_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_bars(
|
||||||
|
&mut self,
|
||||||
|
allocator: &mut SystemAllocator,
|
||||||
|
mmio_allocator: &mut AddressAllocator,
|
||||||
|
) -> Result<(), PciDeviceError> {
|
||||||
|
self.common.free_bars(allocator, mmio_allocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detect_bar_reprogramming(
|
||||||
|
&mut self,
|
||||||
|
reg_idx: usize,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<BarReprogrammingParams> {
|
||||||
|
self.common
|
||||||
|
.configuration
|
||||||
|
.detect_bar_reprogramming(reg_idx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_config_register(
|
||||||
|
&mut self,
|
||||||
|
reg_idx: usize,
|
||||||
|
offset: u64,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Option<Arc<Barrier>> {
|
||||||
|
self.common
|
||||||
|
.write_config_register(reg_idx, offset, data, &self.vfio_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_config_register(&mut self, reg_idx: usize) -> u32 {
|
||||||
|
self.common
|
||||||
|
.read_config_register(reg_idx, &self.vfio_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bar(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
||||||
|
self.common.read_bar(base, offset, data, &self.vfio_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_bar(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
||||||
|
self.common
|
||||||
|
.write_bar(base, offset, data, &self.vfio_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_bar(&mut self, old_base: u64, new_base: u64) -> Result<(), std::io::Error> {
|
||||||
|
info!("Moving BAR 0x{:x} -> 0x{:x}", old_base, new_base);
|
||||||
|
for mmio_region in self.common.mmio_regions.iter_mut() {
|
||||||
|
if mmio_region.start.raw_value() == old_base {
|
||||||
|
mmio_region.start = GuestAddress(new_base);
|
||||||
|
|
||||||
|
if let Some(mem_slot) = mmio_region.mem_slot {
|
||||||
|
if let Some(host_addr) = mmio_region.host_addr {
|
||||||
|
// Remove original region
|
||||||
|
let old_region = self.vm.make_user_memory_region(
|
||||||
|
mem_slot,
|
||||||
|
old_base,
|
||||||
|
mmio_region.length as u64,
|
||||||
|
host_addr as u64,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.vm
|
||||||
|
.remove_user_memory_region(old_region)
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
|
|
||||||
|
let new_region = self.vm.make_user_memory_region(
|
||||||
|
mem_slot,
|
||||||
|
new_base,
|
||||||
|
mmio_region.length as u64,
|
||||||
|
host_addr as u64,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.vm
|
||||||
|
.create_user_memory_region(new_region)
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Moved bar 0x{:x} -> 0x{:x}", old_base, new_base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for VfioUserPciDevice {
|
impl Drop for VfioUserPciDevice {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.unmap_mmio_regions();
|
self.unmap_mmio_regions();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ path = "src/qcow.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
remain = "0.2.2"
|
remain = "0.2.2"
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
@@ -28,8 +28,11 @@ const BLK_ALIGNMENTS: [usize; 2] = [512, 4096];
|
|||||||
|
|
||||||
fn is_valid_alignment(fd: RawFd, alignment: usize) -> bool {
|
fn is_valid_alignment(fd: RawFd, alignment: usize) -> bool {
|
||||||
let layout = Layout::from_size_align(alignment, alignment).unwrap();
|
let layout = Layout::from_size_align(alignment, alignment).unwrap();
|
||||||
|
// SAFETY: layout has non-zero size
|
||||||
let ptr = unsafe { alloc_zeroed(layout) };
|
let ptr = unsafe { alloc_zeroed(layout) };
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
|
||||||
|
// SAFETY: FFI call
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
::libc::pread(
|
::libc::pread(
|
||||||
fd,
|
fd,
|
||||||
@@ -39,6 +42,7 @@ fn is_valid_alignment(fd: RawFd, alignment: usize) -> bool {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SAFETY: ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(ptr, layout) };
|
unsafe { dealloc(ptr, layout) };
|
||||||
|
|
||||||
ret >= 0
|
ret >= 0
|
||||||
@@ -141,11 +145,18 @@ impl Read for RawFile {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let layout = Layout::from_size_align(rounded_len, self.alignment).unwrap();
|
let layout = Layout::from_size_align(rounded_len, self.alignment).unwrap();
|
||||||
|
// SAFETY: layout has non-zero size
|
||||||
let tmp_ptr = unsafe { alloc_zeroed(layout) };
|
let tmp_ptr = unsafe { alloc_zeroed(layout) };
|
||||||
|
if tmp_ptr.is_null() {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: tmp_ptr is valid and at least rounded_len long
|
||||||
let tmp_buf = unsafe { slice::from_raw_parts_mut(tmp_ptr, rounded_len) };
|
let tmp_buf = unsafe { slice::from_raw_parts_mut(tmp_ptr, rounded_len) };
|
||||||
|
|
||||||
// This can eventually replaced with read_at once its interface
|
// This can eventually replaced with read_at once its interface
|
||||||
// has been stabilized.
|
// has been stabilized.
|
||||||
|
// SAFETY: FFI call. All parameters are valid.
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
::libc::pread64(
|
::libc::pread64(
|
||||||
self.file.as_raw_fd(),
|
self.file.as_raw_fd(),
|
||||||
@@ -155,12 +166,14 @@ impl Read for RawFile {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
|
// SAFETY: tmp_ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(tmp_ptr, layout) };
|
unsafe { dealloc(tmp_ptr, layout) };
|
||||||
return Err(io::Error::last_os_error());
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
let read: usize = ret.try_into().unwrap();
|
let read: usize = ret.try_into().unwrap();
|
||||||
if read < file_offset {
|
if read < file_offset {
|
||||||
|
// SAFETY: tmp_ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(tmp_ptr, layout) };
|
unsafe { dealloc(tmp_ptr, layout) };
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
@@ -171,6 +184,7 @@ impl Read for RawFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.copy_from_slice(&tmp_buf[file_offset..(file_offset + buf_len)]);
|
buf.copy_from_slice(&tmp_buf[file_offset..(file_offset + buf_len)]);
|
||||||
|
// SAFETY: tmp_ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(tmp_ptr, layout) };
|
unsafe { dealloc(tmp_ptr, layout) };
|
||||||
|
|
||||||
self.seek(SeekFrom::Current(to_copy.try_into().unwrap()))
|
self.seek(SeekFrom::Current(to_copy.try_into().unwrap()))
|
||||||
@@ -211,11 +225,17 @@ impl Write for RawFile {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let layout = Layout::from_size_align(rounded_len, self.alignment).unwrap();
|
let layout = Layout::from_size_align(rounded_len, self.alignment).unwrap();
|
||||||
|
// SAFETY: layout has non-zero size
|
||||||
let tmp_ptr = unsafe { alloc_zeroed(layout) };
|
let tmp_ptr = unsafe { alloc_zeroed(layout) };
|
||||||
|
if tmp_ptr.is_null() {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
let tmp_buf = unsafe { slice::from_raw_parts_mut(tmp_ptr, rounded_len) };
|
let tmp_buf = unsafe { slice::from_raw_parts_mut(tmp_ptr, rounded_len) };
|
||||||
|
|
||||||
// This can eventually replaced with read_at once its interface
|
// This can eventually replaced with read_at once its interface
|
||||||
// has been stabilized.
|
// has been stabilized.
|
||||||
|
// SAFETY: FFI call
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
::libc::pread64(
|
::libc::pread64(
|
||||||
self.file.as_raw_fd(),
|
self.file.as_raw_fd(),
|
||||||
@@ -225,6 +245,7 @@ impl Write for RawFile {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
|
// SAFETY: tmp_ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(tmp_ptr, layout) };
|
unsafe { dealloc(tmp_ptr, layout) };
|
||||||
return Err(io::Error::last_os_error());
|
return Err(io::Error::last_os_error());
|
||||||
};
|
};
|
||||||
@@ -233,6 +254,7 @@ impl Write for RawFile {
|
|||||||
|
|
||||||
// This can eventually replaced with write_at once its interface
|
// This can eventually replaced with write_at once its interface
|
||||||
// has been stabilized.
|
// has been stabilized.
|
||||||
|
// SAFETY: FFI call
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
::libc::pwrite64(
|
::libc::pwrite64(
|
||||||
self.file.as_raw_fd(),
|
self.file.as_raw_fd(),
|
||||||
@@ -242,6 +264,7 @@ impl Write for RawFile {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SAFETY: tmp_ptr was allocated by alloc_zeroed with layout
|
||||||
unsafe { dealloc(tmp_ptr, layout) };
|
unsafe { dealloc(tmp_ptr, layout) };
|
||||||
|
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ version = "0.1.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.103"
|
libc = "0.2.112"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
vmm-sys-util = "0.9.0"
|
vmm-sys-util = "0.9.0"
|
||||||
|
|||||||
194
release-notes.md
194
release-notes.md
@@ -1,3 +1,19 @@
|
|||||||
|
- [v21.1](#v211)
|
||||||
|
- [v21.0](#v210)
|
||||||
|
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
|
||||||
|
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
|
||||||
|
- [Notable Bug fixes](#notable-bug-fixes)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [v20.2](#v202)
|
||||||
|
- [v20.1](#v201)
|
||||||
|
- [v20.0](#v200)
|
||||||
|
- [Multiple PCI segments support](#multiple-pci-segments-support)
|
||||||
|
- [CPU pinning](#cpu-pinning)
|
||||||
|
- [Improved VFIO support](#improved-vfio-support)
|
||||||
|
- [Safer code](#safer-code)
|
||||||
|
- [Extended documentation](#extended-documentation)
|
||||||
|
- [Notable bug fixes](#notable-bug-fixes-1)
|
||||||
|
- [Contributors](#contributors-1)
|
||||||
- [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)
|
||||||
@@ -5,8 +21,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)
|
- [Notable bug fixes](#notable-bug-fixes-2)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors-2)
|
||||||
- [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)
|
||||||
@@ -16,23 +32,23 @@
|
|||||||
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
||||||
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
||||||
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
||||||
- [Notable bug fixes](#notable-bug-fixes-1)
|
- [Notable bug fixes](#notable-bug-fixes-3)
|
||||||
- [Contributors](#contributors-1)
|
- [Contributors](#contributors-3)
|
||||||
- [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-2)
|
- [Notable bug fixes](#notable-bug-fixes-4)
|
||||||
- [Contributors](#contributors-2)
|
- [Contributors](#contributors-4)
|
||||||
- [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-3)
|
- [Notable bug fixes](#notable-bug-fixes-5)
|
||||||
- [Removed functionality](#removed-functionality)
|
- [Removed functionality](#removed-functionality)
|
||||||
- [Contributors](#contributors-3)
|
- [Contributors](#contributors-5)
|
||||||
- [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)
|
||||||
@@ -40,7 +56,7 @@
|
|||||||
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
||||||
- [Bug fixes](#bug-fixes)
|
- [Bug fixes](#bug-fixes)
|
||||||
- [Deprecations](#deprecations)
|
- [Deprecations](#deprecations)
|
||||||
- [Contributors](#contributors-4)
|
- [Contributors](#contributors-6)
|
||||||
- [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)
|
||||||
@@ -50,7 +66,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-1)
|
- [Deprecations](#deprecations-1)
|
||||||
- [Contributors](#contributors-5)
|
- [Contributors](#contributors-7)
|
||||||
- [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)
|
||||||
@@ -58,13 +74,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-6)
|
- [Contributors](#contributors-8)
|
||||||
- [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-7)
|
- [Contributors](#contributors-9)
|
||||||
- [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)
|
||||||
@@ -76,15 +92,15 @@
|
|||||||
- [Default Log Level Changed](#default-log-level-changed)
|
- [Default Log Level Changed](#default-log-level-changed)
|
||||||
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
||||||
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
||||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||||
- [Contributors](#contributors-8)
|
- [Contributors](#contributors-10)
|
||||||
- [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-5)
|
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||||
- [Contributors](#contributors-9)
|
- [Contributors](#contributors-11)
|
||||||
- [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)
|
||||||
@@ -97,17 +113,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-6)
|
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||||
- [Contributors](#contributors-10)
|
- [Contributors](#contributors-12)
|
||||||
- [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-7)
|
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||||
- [Contributors](#contributors-11)
|
- [Contributors](#contributors-13)
|
||||||
- [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)
|
||||||
@@ -117,14 +133,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-12)
|
- [Contributors](#contributors-14)
|
||||||
- [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-13)
|
- [Contributors](#contributors-15)
|
||||||
- [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)
|
||||||
@@ -132,7 +148,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-14)
|
- [Contributors](#contributors-16)
|
||||||
- [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)
|
||||||
@@ -141,7 +157,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-15)
|
- [Contributors](#contributors-17)
|
||||||
- [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)
|
||||||
@@ -168,6 +184,134 @@
|
|||||||
- [Unit testing](#unit-testing)
|
- [Unit testing](#unit-testing)
|
||||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||||
|
|
||||||
|
# v21.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Missing `openat()` syscall from seccomp filter (#3609)
|
||||||
|
* Ensure MMIO/PIO exits complete before pausing (#3658)
|
||||||
|
* Support DWORD writes to MSI-X control register (#3714)
|
||||||
|
* VFIO ioctl reordering to fix MSI on AMD platforms (#3827)
|
||||||
|
* Fix `virtio-net` control queue (#3829)
|
||||||
|
|
||||||
|
# v21.0
|
||||||
|
|
||||||
|
This release has been tracked through the [v21.0
|
||||||
|
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/24).
|
||||||
|
|
||||||
|
### Efficient Local Live Migration (for Live Upgrade)
|
||||||
|
|
||||||
|
In order to support fast live upgrade of the VMM an optimised path has been added in which the memory for the VM is not compared from source to destination. This is activated by passing `--local` to the `ch-remote send-migration` command. This means that the live upgrade can complete in the order of 50ms vs 3s. (#3566)
|
||||||
|
|
||||||
|
### Recommended Kernel is Now 5.15
|
||||||
|
|
||||||
|
Due to an issue in the `virtio-net` code in 5.14 the recommended Linux kernel is now 5.15. (#3530)
|
||||||
|
|
||||||
|
### Notable Bug fixes
|
||||||
|
|
||||||
|
* Multiple fixes were made to the OpenAPI YAML file to match the implementaion (#3555,#3562)
|
||||||
|
* Avoid live migration deadlock when triggered during the kernel boot (#3585)
|
||||||
|
* Support live migration within firmware (#3586)
|
||||||
|
* Validate the `virtio-net` desciptor chain (#3548)
|
||||||
|
* `direct=on` (`O_DIRECT`) can now be used with a guest that makes unaligned accesses (e.g. firmware) (#3587)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||||
|
* Barret Rhoden <brho@google.com>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Fabiano Fidêncio <fabiano.fidencio@intel.com>
|
||||||
|
* Henry Wang <Henry.Wang@arm.com>
|
||||||
|
* Liang Zhou <zhoul110@chinatelecom.cn>
|
||||||
|
* Michael Zhao <michael.zhao@arm.com>
|
||||||
|
* Muhammad Falak R Wani <falakreyaz@gmail.com>
|
||||||
|
* Muminul Islam <muislam@microsoft.com>
|
||||||
|
* Rob Bradford <robert.bradford@intel.com>
|
||||||
|
* Sebastien Boeuf <sebastien.boeuf@intel.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
* Ziye Yang <ziye.yang@intel.com>
|
||||||
|
|
||||||
|
# v20.2
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Don't error out when setting up the SIGWINCH handler (for console resize)
|
||||||
|
when this fails due to older kernel (#3456)
|
||||||
|
* Seccomp rules were refined to remove syscalls that are now unused
|
||||||
|
* Fix reboot on older host kernels when SIGWINCH handler was not initialised
|
||||||
|
(#3496)
|
||||||
|
* Fix virtio-vsock blocking issue (#3497)
|
||||||
|
|
||||||
|
# v20.1
|
||||||
|
|
||||||
|
This is a bug fix release. The following issues have been addressed:
|
||||||
|
|
||||||
|
* Networking performance regression with `virtio-net` (#3450)
|
||||||
|
* Limit file descriptors sent in `vfio-user` support (#3401)
|
||||||
|
* Fully advertise PCI MMIO config regions in ACPI tables (#3432)
|
||||||
|
* Set the TSS and KVM identity maps so they don't overlap with firmware RAM
|
||||||
|
* Correctly update the `DeviceTree` on restore
|
||||||
|
|
||||||
|
# v20.0
|
||||||
|
|
||||||
|
This release has been tracked through the [v20.0
|
||||||
|
project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/23).
|
||||||
|
|
||||||
|
### Multiple PCI segments support
|
||||||
|
|
||||||
|
Cloud Hypervisor is no longer limited to 31 PCI devices. For both `x86_64` and
|
||||||
|
`aarch64` architectures, it is now possible to create up to 16 PCI segments,
|
||||||
|
increasing the total amount of supported PCI devices to 496.
|
||||||
|
|
||||||
|
### CPU pinning
|
||||||
|
|
||||||
|
For each vCPU, the user can define a limited set of host CPUs on which it is
|
||||||
|
allowed to run. This can be useful when assigning a 1:1 mapping between host and
|
||||||
|
guest resources, or when running a VM on a specific NUMA node.
|
||||||
|
|
||||||
|
### Improved VFIO support
|
||||||
|
|
||||||
|
Based on VFIO region capabilities, all regions can be memory mapped, limiting
|
||||||
|
the amount of triggered VM exits, and therefore increasing the performance of
|
||||||
|
the passthrough device.
|
||||||
|
|
||||||
|
### Safer code
|
||||||
|
|
||||||
|
Several sections containing unsafe Rust code have been replaced with safe
|
||||||
|
alternatives, and multiple comments have been added to clarify why the remaining
|
||||||
|
unsafe sections are safe to use.
|
||||||
|
|
||||||
|
### Extended documentation
|
||||||
|
|
||||||
|
The documentation related to VFIO has been updated while some new documents have
|
||||||
|
been introduced to cover the usage of `--cpus` parameter as well as how to run
|
||||||
|
Cloud Hypervisor on Intel TDX.
|
||||||
|
|
||||||
|
### Notable bug fixes
|
||||||
|
|
||||||
|
* Naturally align PCI BARs on relocation (#3244)
|
||||||
|
* Fix panic in SIGWINCH listener thread when no seccomp filter set (#3338)
|
||||||
|
* Use the tty raw mode implementation from libc (#3344)
|
||||||
|
* Fix the emulation of register D for CMOS/RTC device (#3393)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Many thanks to everyone who has contributed to our release:
|
||||||
|
|
||||||
|
* Alyssa Ross <hi@alyssa.is>
|
||||||
|
* Bo Chen <chen.bo@intel.com>
|
||||||
|
* Fabiano Fidêncio <fabiano.fidencio@intel.com>
|
||||||
|
* Michael Zhao <michael.zhao@arm.com>
|
||||||
|
* Muminul Islam <muislam@microsoft.com>
|
||||||
|
* Rob Bradford <robert.bradford@intel.com>
|
||||||
|
* Sebastien Boeuf <sebastien.boeuf@intel.com>
|
||||||
|
* Wei Liu <liuwe@microsoft.com>
|
||||||
|
* Willen Yang <willenyang@gmail.com>
|
||||||
|
* William Douglas <william.douglas@intel.com>
|
||||||
|
* Ziye Yang <ziye.yang@intel.com>
|
||||||
|
|
||||||
# v19.0
|
# v19.0
|
||||||
|
|
||||||
This release has been tracked through the [v19.0
|
This release has been tracked through the [v19.0
|
||||||
@@ -1244,7 +1388,7 @@ Highlights for `cloud-hypervisor` version 0.4.0 include:
|
|||||||
|
|
||||||
### Dynamic virtual CPUs addition
|
### Dynamic virtual CPUs addition
|
||||||
|
|
||||||
As a way to vertically scale Cloud-Hypervisor guests, we now support dynamically
|
As a way to vertically scale Cloud Hypervisor guests, we now support dynamically
|
||||||
adding virtual CPUs to the guests, a mechanism also known as CPU hot plug.
|
adding virtual CPUs to the guests, a mechanism also known as CPU hot plug.
|
||||||
Through hardware-reduced ACPI notifications, Cloud Hypervisor can now add CPUs
|
Through hardware-reduced ACPI notifications, Cloud Hypervisor can now add CPUs
|
||||||
to an already running guest and the high level operations for that process are
|
to an already running guest and the high level operations for that process are
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:20.04 as dev
|
FROM ubuntu:20.04 as dev
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG RUST_TOOLCHAIN="1.55.0"
|
ARG RUST_TOOLCHAIN="1.58.0"
|
||||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||||
@@ -111,16 +111,18 @@ RUN git clone --depth 1 https://gitlab.com/virtio-fs/qemu.git -b qemu5.0-virtiof
|
|||||||
&& cd .. && rm -rf qemu
|
&& cd .. && rm -rf qemu
|
||||||
|
|
||||||
# install SPDK NVMe
|
# install SPDK NVMe
|
||||||
RUN git clone https://github.com/spdk/spdk \
|
# only for 'x86_64' platform images as 'docker buildx' can't build 'spdk'
|
||||||
&& cd spdk \
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
&& git checkout a827fd7eeca67209d4c0aaad9a3ed55692e7e36e \
|
git clone https://github.com/spdk/spdk \
|
||||||
&& git submodule update --init \
|
&& cd spdk \
|
||||||
&& apt-get update \
|
&& git checkout 59f3cdacb13bd2a19c4a86be04792b0ee4491172 \
|
||||||
&& ./scripts/pkgdep.sh \
|
&& git submodule update --init \
|
||||||
&& ./configure --with-vfio-user \
|
&& apt-get update \
|
||||||
&& make -j `nproc` \
|
&& ./scripts/pkgdep.sh \
|
||||||
&& mkdir /usr/local/bin/spdk-nvme \
|
&& ./configure --with-vfio-user \
|
||||||
&& cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
&& make -j `nproc` \
|
||||||
&& cp ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
&& mkdir /usr/local/bin/spdk-nvme \
|
||||||
&& cp -r ./scripts/rpc /usr/local/bin/spdk-nvme \
|
&& cp ./build/bin/nvmf_tgt /usr/local/bin/spdk-nvme \
|
||||||
&& cd .. && rm -rf spdk
|
&& cp ./scripts/rpc.py /usr/local/bin/spdk-nvme \
|
||||||
|
&& cp -r ./scripts/rpc /usr/local/bin/spdk-nvme \
|
||||||
|
&& cd .. && rm -rf spdk; fi
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Linux/arm64 5.14.0 Kernel Configuration
|
# Linux/arm64 5.15.12 Kernel Configuration
|
||||||
#
|
#
|
||||||
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
|
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
|
||||||
CONFIG_CC_IS_GCC=y
|
CONFIG_CC_IS_GCC=y
|
||||||
@@ -25,6 +25,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
|
|||||||
#
|
#
|
||||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
# CONFIG_COMPILE_TEST is not set
|
# CONFIG_COMPILE_TEST is not set
|
||||||
|
# CONFIG_WERROR is not set
|
||||||
CONFIG_LOCALVERSION=""
|
CONFIG_LOCALVERSION=""
|
||||||
# CONFIG_LOCALVERSION_AUTO is not set
|
# CONFIG_LOCALVERSION_AUTO is not set
|
||||||
CONFIG_BUILD_SALT=""
|
CONFIG_BUILD_SALT=""
|
||||||
@@ -133,6 +134,7 @@ CONFIG_RCU_NEED_SEGCBLIST=y
|
|||||||
CONFIG_LOG_BUF_SHIFT=21
|
CONFIG_LOG_BUF_SHIFT=21
|
||||||
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
|
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
|
||||||
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
|
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
|
||||||
|
# CONFIG_PRINTK_INDEX is not set
|
||||||
CONFIG_GENERIC_SCHED_CLOCK=y
|
CONFIG_GENERIC_SCHED_CLOCK=y
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -202,7 +204,6 @@ CONFIG_SYSFS_SYSCALL=y
|
|||||||
CONFIG_FHANDLE=y
|
CONFIG_FHANDLE=y
|
||||||
CONFIG_POSIX_TIMERS=y
|
CONFIG_POSIX_TIMERS=y
|
||||||
CONFIG_PRINTK=y
|
CONFIG_PRINTK=y
|
||||||
CONFIG_PRINTK_NMI=y
|
|
||||||
CONFIG_BUG=y
|
CONFIG_BUG=y
|
||||||
CONFIG_ELF_CORE=y
|
CONFIG_ELF_CORE=y
|
||||||
CONFIG_BASE_FULL=y
|
CONFIG_BASE_FULL=y
|
||||||
@@ -265,7 +266,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
|
|||||||
CONFIG_STACKTRACE_SUPPORT=y
|
CONFIG_STACKTRACE_SUPPORT=y
|
||||||
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
||||||
CONFIG_LOCKDEP_SUPPORT=y
|
CONFIG_LOCKDEP_SUPPORT=y
|
||||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
|
||||||
CONFIG_GENERIC_BUG=y
|
CONFIG_GENERIC_BUG=y
|
||||||
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||||
CONFIG_GENERIC_HWEIGHT=y
|
CONFIG_GENERIC_HWEIGHT=y
|
||||||
@@ -431,8 +431,10 @@ CONFIG_ARM64_CNP=y
|
|||||||
#
|
#
|
||||||
CONFIG_ARM64_PTR_AUTH=y
|
CONFIG_ARM64_PTR_AUTH=y
|
||||||
CONFIG_ARM64_PTR_AUTH_KERNEL=y
|
CONFIG_ARM64_PTR_AUTH_KERNEL=y
|
||||||
|
CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y
|
||||||
CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y
|
CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y
|
||||||
CONFIG_AS_HAS_PAC=y
|
CONFIG_AS_HAS_PAC=y
|
||||||
|
CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y
|
||||||
# end of ARMv8.3 architectural features
|
# end of ARMv8.3 architectural features
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -446,9 +448,13 @@ CONFIG_ARM64_TLB_RANGE=y
|
|||||||
#
|
#
|
||||||
# ARMv8.5 architectural features
|
# ARMv8.5 architectural features
|
||||||
#
|
#
|
||||||
|
CONFIG_AS_HAS_ARMV8_5=y
|
||||||
CONFIG_ARM64_BTI=y
|
CONFIG_ARM64_BTI=y
|
||||||
|
CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y
|
||||||
CONFIG_ARM64_E0PD=y
|
CONFIG_ARM64_E0PD=y
|
||||||
CONFIG_ARCH_RANDOM=y
|
CONFIG_ARCH_RANDOM=y
|
||||||
|
CONFIG_ARM64_AS_HAS_MTE=y
|
||||||
|
CONFIG_ARM64_MTE=y
|
||||||
# end of ARMv8.5 architectural features
|
# end of ARMv8.5 architectural features
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -462,6 +468,8 @@ CONFIG_ARM64_SVE=y
|
|||||||
CONFIG_RELOCATABLE=y
|
CONFIG_RELOCATABLE=y
|
||||||
CONFIG_RANDOMIZE_BASE=y
|
CONFIG_RANDOMIZE_BASE=y
|
||||||
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
|
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
|
||||||
|
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
||||||
|
CONFIG_STACKPROTECTOR_PER_TASK=y
|
||||||
# end of Kernel Features
|
# end of Kernel Features
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -543,49 +551,6 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
|||||||
# end of CPU Frequency scaling
|
# end of CPU Frequency scaling
|
||||||
# end of CPU Power Management
|
# end of CPU Power Management
|
||||||
|
|
||||||
#
|
|
||||||
# Firmware Drivers
|
|
||||||
#
|
|
||||||
# CONFIG_ARM_SCMI_PROTOCOL is not set
|
|
||||||
# CONFIG_ARM_SCPI_PROTOCOL is not set
|
|
||||||
# CONFIG_ARM_SDE_INTERFACE is not set
|
|
||||||
CONFIG_FIRMWARE_MEMMAP=y
|
|
||||||
CONFIG_DMIID=y
|
|
||||||
CONFIG_DMI_SYSFS=y
|
|
||||||
# CONFIG_FW_CFG_SYSFS is not set
|
|
||||||
# CONFIG_ARM_FFA_TRANSPORT is not set
|
|
||||||
# CONFIG_GOOGLE_FIRMWARE is not set
|
|
||||||
|
|
||||||
#
|
|
||||||
# EFI (Extensible Firmware Interface) Support
|
|
||||||
#
|
|
||||||
CONFIG_EFI_ESRT=y
|
|
||||||
CONFIG_EFI_PARAMS_FROM_FDT=y
|
|
||||||
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
|
||||||
CONFIG_EFI_GENERIC_STUB=y
|
|
||||||
CONFIG_EFI_ARMSTUB_DTB_LOADER=y
|
|
||||||
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
|
||||||
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
|
||||||
# CONFIG_EFI_CAPSULE_LOADER is not set
|
|
||||||
# CONFIG_EFI_TEST is not set
|
|
||||||
# CONFIG_RESET_ATTACK_MITIGATION is not set
|
|
||||||
# CONFIG_EFI_DISABLE_PCI_DMA is not set
|
|
||||||
# end of EFI (Extensible Firmware Interface) Support
|
|
||||||
|
|
||||||
CONFIG_EFI_EARLYCON=y
|
|
||||||
# CONFIG_EFI_CUSTOM_SSDT_OVERLAYS is not set
|
|
||||||
CONFIG_ARM_PSCI_FW=y
|
|
||||||
# CONFIG_ARM_PSCI_CHECKER is not set
|
|
||||||
CONFIG_HAVE_ARM_SMCCC=y
|
|
||||||
CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y
|
|
||||||
# CONFIG_ARM_SMCCC_SOC_ID is not set
|
|
||||||
|
|
||||||
#
|
|
||||||
# Tegra firmware driver
|
|
||||||
#
|
|
||||||
# end of Tegra firmware driver
|
|
||||||
# end of Firmware Drivers
|
|
||||||
|
|
||||||
CONFIG_ARCH_SUPPORTS_ACPI=y
|
CONFIG_ARCH_SUPPORTS_ACPI=y
|
||||||
CONFIG_ACPI=y
|
CONFIG_ACPI=y
|
||||||
CONFIG_ACPI_GENERIC_GSI=y
|
CONFIG_ACPI_GENERIC_GSI=y
|
||||||
@@ -640,6 +605,8 @@ CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y
|
|||||||
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
|
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
|
||||||
CONFIG_HAVE_KVM_IRQ_BYPASS=y
|
CONFIG_HAVE_KVM_IRQ_BYPASS=y
|
||||||
CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y
|
CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y
|
||||||
|
CONFIG_KVM_XFER_TO_GUEST_WORK=y
|
||||||
|
# CONFIG_NVHE_EL2_DEBUG is not set
|
||||||
# CONFIG_ARM64_CRYPTO is not set
|
# CONFIG_ARM64_CRYPTO is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -654,6 +621,7 @@ CONFIG_HAVE_KPROBES=y
|
|||||||
CONFIG_HAVE_KRETPROBES=y
|
CONFIG_HAVE_KRETPROBES=y
|
||||||
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
|
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
|
||||||
CONFIG_HAVE_NMI=y
|
CONFIG_HAVE_NMI=y
|
||||||
|
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||||
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
||||||
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
||||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||||
@@ -738,15 +706,14 @@ CONFIG_BASE_SMALL=0
|
|||||||
# CONFIG_MODULES is not set
|
# CONFIG_MODULES is not set
|
||||||
CONFIG_MODULES_TREE_LOOKUP=y
|
CONFIG_MODULES_TREE_LOOKUP=y
|
||||||
CONFIG_BLOCK=y
|
CONFIG_BLOCK=y
|
||||||
CONFIG_BLK_SCSI_REQUEST=y
|
|
||||||
CONFIG_BLK_CGROUP_RWSTAT=y
|
CONFIG_BLK_CGROUP_RWSTAT=y
|
||||||
CONFIG_BLK_DEV_BSG=y
|
CONFIG_BLK_DEV_BSG_COMMON=y
|
||||||
CONFIG_BLK_DEV_BSGLIB=y
|
CONFIG_BLK_DEV_BSGLIB=y
|
||||||
CONFIG_BLK_DEV_INTEGRITY=y
|
CONFIG_BLK_DEV_INTEGRITY=y
|
||||||
|
CONFIG_BLK_DEV_INTEGRITY_T10=y
|
||||||
# CONFIG_BLK_DEV_ZONED is not set
|
# CONFIG_BLK_DEV_ZONED is not set
|
||||||
CONFIG_BLK_DEV_THROTTLING=y
|
CONFIG_BLK_DEV_THROTTLING=y
|
||||||
# CONFIG_BLK_DEV_THROTTLING_LOW is not set
|
# CONFIG_BLK_DEV_THROTTLING_LOW is not set
|
||||||
CONFIG_BLK_CMDLINE_PARSER=y
|
|
||||||
CONFIG_BLK_WBT=y
|
CONFIG_BLK_WBT=y
|
||||||
CONFIG_BLK_WBT_MQ=y
|
CONFIG_BLK_WBT_MQ=y
|
||||||
# CONFIG_BLK_CGROUP_IOLATENCY is not set
|
# CONFIG_BLK_CGROUP_IOLATENCY is not set
|
||||||
@@ -936,11 +903,18 @@ CONFIG_ZONE_DMA32=y
|
|||||||
CONFIG_ZONE_DEVICE=y
|
CONFIG_ZONE_DEVICE=y
|
||||||
CONFIG_DEV_PAGEMAP_OPS=y
|
CONFIG_DEV_PAGEMAP_OPS=y
|
||||||
# CONFIG_DEVICE_PRIVATE is not set
|
# CONFIG_DEVICE_PRIVATE is not set
|
||||||
|
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
|
||||||
CONFIG_PERCPU_STATS=y
|
CONFIG_PERCPU_STATS=y
|
||||||
# CONFIG_GUP_TEST is not set
|
# CONFIG_GUP_TEST is not set
|
||||||
# CONFIG_READ_ONLY_THP_FOR_FS is not set
|
# CONFIG_READ_ONLY_THP_FOR_FS is not set
|
||||||
CONFIG_ARCH_HAS_PTE_SPECIAL=y
|
CONFIG_ARCH_HAS_PTE_SPECIAL=y
|
||||||
CONFIG_SECRETMEM=y
|
CONFIG_SECRETMEM=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Data Access Monitoring
|
||||||
|
#
|
||||||
|
# CONFIG_DAMON is not set
|
||||||
|
# end of Data Access Monitoring
|
||||||
# end of Memory Management options
|
# end of Memory Management options
|
||||||
|
|
||||||
CONFIG_NET=y
|
CONFIG_NET=y
|
||||||
@@ -953,6 +927,7 @@ CONFIG_PACKET=y
|
|||||||
CONFIG_PACKET_DIAG=y
|
CONFIG_PACKET_DIAG=y
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
CONFIG_UNIX_SCM=y
|
CONFIG_UNIX_SCM=y
|
||||||
|
CONFIG_AF_UNIX_OOB=y
|
||||||
CONFIG_UNIX_DIAG=y
|
CONFIG_UNIX_DIAG=y
|
||||||
CONFIG_TLS=y
|
CONFIG_TLS=y
|
||||||
# CONFIG_TLS_DEVICE is not set
|
# CONFIG_TLS_DEVICE is not set
|
||||||
@@ -1056,6 +1031,7 @@ CONFIG_NET_FLOW_LIMIT=y
|
|||||||
# CONFIG_AF_RXRPC is not set
|
# CONFIG_AF_RXRPC is not set
|
||||||
# CONFIG_AF_KCM is not set
|
# CONFIG_AF_KCM is not set
|
||||||
CONFIG_STREAM_PARSER=y
|
CONFIG_STREAM_PARSER=y
|
||||||
|
# CONFIG_MCTP is not set
|
||||||
# CONFIG_WIRELESS is not set
|
# CONFIG_WIRELESS is not set
|
||||||
# CONFIG_RFKILL is not set
|
# CONFIG_RFKILL is not set
|
||||||
# CONFIG_NET_9P is not set
|
# CONFIG_NET_9P is not set
|
||||||
@@ -1202,13 +1178,64 @@ CONFIG_GENERIC_ARCH_NUMA=y
|
|||||||
# Bus devices
|
# Bus devices
|
||||||
#
|
#
|
||||||
# CONFIG_BRCMSTB_GISB_ARB is not set
|
# CONFIG_BRCMSTB_GISB_ARB is not set
|
||||||
# CONFIG_SIMPLE_PM_BUS is not set
|
|
||||||
# CONFIG_VEXPRESS_CONFIG is not set
|
# CONFIG_VEXPRESS_CONFIG is not set
|
||||||
# CONFIG_MHI_BUS is not set
|
# CONFIG_MHI_BUS is not set
|
||||||
# end of Bus devices
|
# end of Bus devices
|
||||||
|
|
||||||
CONFIG_CONNECTOR=y
|
CONFIG_CONNECTOR=y
|
||||||
CONFIG_PROC_EVENTS=y
|
CONFIG_PROC_EVENTS=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Firmware Drivers
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# ARM System Control and Management Interface Protocol
|
||||||
|
#
|
||||||
|
# CONFIG_ARM_SCMI_PROTOCOL is not set
|
||||||
|
# end of ARM System Control and Management Interface Protocol
|
||||||
|
|
||||||
|
# CONFIG_ARM_SCPI_PROTOCOL is not set
|
||||||
|
# CONFIG_ARM_SDE_INTERFACE is not set
|
||||||
|
CONFIG_FIRMWARE_MEMMAP=y
|
||||||
|
CONFIG_DMIID=y
|
||||||
|
CONFIG_DMI_SYSFS=y
|
||||||
|
# CONFIG_FW_CFG_SYSFS is not set
|
||||||
|
CONFIG_SYSFB=y
|
||||||
|
# CONFIG_SYSFB_SIMPLEFB is not set
|
||||||
|
# CONFIG_ARM_FFA_TRANSPORT is not set
|
||||||
|
# CONFIG_GOOGLE_FIRMWARE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# EFI (Extensible Firmware Interface) Support
|
||||||
|
#
|
||||||
|
CONFIG_EFI_ESRT=y
|
||||||
|
CONFIG_EFI_PARAMS_FROM_FDT=y
|
||||||
|
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
||||||
|
CONFIG_EFI_GENERIC_STUB=y
|
||||||
|
CONFIG_EFI_ARMSTUB_DTB_LOADER=y
|
||||||
|
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
||||||
|
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
||||||
|
# CONFIG_EFI_CAPSULE_LOADER is not set
|
||||||
|
# CONFIG_EFI_TEST is not set
|
||||||
|
# CONFIG_RESET_ATTACK_MITIGATION is not set
|
||||||
|
# CONFIG_EFI_DISABLE_PCI_DMA is not set
|
||||||
|
# end of EFI (Extensible Firmware Interface) Support
|
||||||
|
|
||||||
|
CONFIG_EFI_EARLYCON=y
|
||||||
|
# CONFIG_EFI_CUSTOM_SSDT_OVERLAYS is not set
|
||||||
|
CONFIG_ARM_PSCI_FW=y
|
||||||
|
# CONFIG_ARM_PSCI_CHECKER is not set
|
||||||
|
CONFIG_HAVE_ARM_SMCCC=y
|
||||||
|
CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y
|
||||||
|
# CONFIG_ARM_SMCCC_SOC_ID is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tegra firmware driver
|
||||||
|
#
|
||||||
|
# end of Tegra firmware driver
|
||||||
|
# end of Firmware Drivers
|
||||||
|
|
||||||
# CONFIG_GNSS is not set
|
# CONFIG_GNSS is not set
|
||||||
# CONFIG_MTD is not set
|
# CONFIG_MTD is not set
|
||||||
CONFIG_DTC=y
|
CONFIG_DTC=y
|
||||||
@@ -1258,7 +1285,9 @@ CONFIG_VIRTIO_BLK=y
|
|||||||
#
|
#
|
||||||
# NVME Support
|
# NVME Support
|
||||||
#
|
#
|
||||||
# CONFIG_BLK_DEV_NVME is not set
|
CONFIG_NVME_CORE=y
|
||||||
|
CONFIG_BLK_DEV_NVME=y
|
||||||
|
CONFIG_NVME_MULTIPATH=y
|
||||||
# CONFIG_NVME_FC is not set
|
# CONFIG_NVME_FC is not set
|
||||||
# CONFIG_NVME_TCP is not set
|
# CONFIG_NVME_TCP is not set
|
||||||
# CONFIG_NVME_TARGET is not set
|
# CONFIG_NVME_TARGET is not set
|
||||||
@@ -1315,7 +1344,38 @@ CONFIG_SCSI_MOD=y
|
|||||||
|
|
||||||
CONFIG_HAVE_PATA_PLATFORM=y
|
CONFIG_HAVE_PATA_PLATFORM=y
|
||||||
# CONFIG_ATA is not set
|
# CONFIG_ATA is not set
|
||||||
# CONFIG_MD is not set
|
CONFIG_MD=y
|
||||||
|
# CONFIG_BLK_DEV_MD is not set
|
||||||
|
# CONFIG_BCACHE is not set
|
||||||
|
CONFIG_BLK_DEV_DM_BUILTIN=y
|
||||||
|
CONFIG_BLK_DEV_DM=y
|
||||||
|
# CONFIG_DM_DEBUG is not set
|
||||||
|
# CONFIG_DM_UNSTRIPED is not set
|
||||||
|
# CONFIG_DM_CRYPT is not set
|
||||||
|
# CONFIG_DM_SNAPSHOT is not set
|
||||||
|
# CONFIG_DM_THIN_PROVISIONING is not set
|
||||||
|
# CONFIG_DM_CACHE is not set
|
||||||
|
# CONFIG_DM_WRITECACHE is not set
|
||||||
|
# CONFIG_DM_EBS is not set
|
||||||
|
# CONFIG_DM_ERA is not set
|
||||||
|
# CONFIG_DM_CLONE is not set
|
||||||
|
# CONFIG_DM_MIRROR is not set
|
||||||
|
# CONFIG_DM_RAID is not set
|
||||||
|
# CONFIG_DM_ZERO is not set
|
||||||
|
CONFIG_DM_MULTIPATH=y
|
||||||
|
# CONFIG_DM_MULTIPATH_QL is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_ST is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_HST is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_IOA is not set
|
||||||
|
# CONFIG_DM_DELAY is not set
|
||||||
|
# CONFIG_DM_DUST is not set
|
||||||
|
# CONFIG_DM_INIT is not set
|
||||||
|
# CONFIG_DM_UEVENT is not set
|
||||||
|
# CONFIG_DM_FLAKEY is not set
|
||||||
|
# CONFIG_DM_VERITY is not set
|
||||||
|
# CONFIG_DM_SWITCH is not set
|
||||||
|
# CONFIG_DM_LOG_WRITES is not set
|
||||||
|
# CONFIG_DM_INTEGRITY is not set
|
||||||
# CONFIG_TARGET_CORE is not set
|
# CONFIG_TARGET_CORE is not set
|
||||||
# CONFIG_FUSION is not set
|
# CONFIG_FUSION is not set
|
||||||
|
|
||||||
@@ -1379,7 +1439,6 @@ CONFIG_VIRTIO_NET=y
|
|||||||
# CONFIG_NETDEVSIM is not set
|
# CONFIG_NETDEVSIM is not set
|
||||||
CONFIG_NET_FAILOVER=y
|
CONFIG_NET_FAILOVER=y
|
||||||
# CONFIG_ISDN is not set
|
# CONFIG_ISDN is not set
|
||||||
# CONFIG_NVM is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Input device support
|
# Input device support
|
||||||
@@ -1523,15 +1582,15 @@ CONFIG_HW_RANDOM_VIRTIO=y
|
|||||||
CONFIG_HW_RANDOM_CAVIUM=y
|
CONFIG_HW_RANDOM_CAVIUM=y
|
||||||
# CONFIG_HW_RANDOM_CCTRNG is not set
|
# CONFIG_HW_RANDOM_CCTRNG is not set
|
||||||
# CONFIG_HW_RANDOM_XIPHERA is not set
|
# CONFIG_HW_RANDOM_XIPHERA is not set
|
||||||
|
CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=y
|
||||||
# CONFIG_APPLICOM is not set
|
# CONFIG_APPLICOM is not set
|
||||||
CONFIG_DEVMEM=y
|
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
|
||||||
# end of Character devices
|
|
||||||
|
|
||||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||||
|
# end of Character devices
|
||||||
|
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
@@ -1561,12 +1620,12 @@ CONFIG_PPS_CLIENT_GPIO=y
|
|||||||
# PTP clock support
|
# PTP clock support
|
||||||
#
|
#
|
||||||
CONFIG_PTP_1588_CLOCK=y
|
CONFIG_PTP_1588_CLOCK=y
|
||||||
|
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
|
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
|
||||||
#
|
#
|
||||||
CONFIG_PTP_1588_CLOCK_KVM=y
|
CONFIG_PTP_1588_CLOCK_KVM=y
|
||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
@@ -1620,6 +1679,7 @@ CONFIG_GPIO_PL061=y
|
|||||||
#
|
#
|
||||||
# CONFIG_GPIO_AGGREGATOR is not set
|
# CONFIG_GPIO_AGGREGATOR is not set
|
||||||
# CONFIG_GPIO_MOCKUP is not set
|
# CONFIG_GPIO_MOCKUP is not set
|
||||||
|
# CONFIG_GPIO_VIRTIO is not set
|
||||||
# end of Virtual GPIO drivers
|
# end of Virtual GPIO drivers
|
||||||
|
|
||||||
# CONFIG_W1 is not set
|
# CONFIG_W1 is not set
|
||||||
@@ -1838,7 +1898,6 @@ CONFIG_HID_GENERIC=y
|
|||||||
# CONFIG_HID_AUREAL is not set
|
# CONFIG_HID_AUREAL is not set
|
||||||
# CONFIG_HID_BELKIN is not set
|
# CONFIG_HID_BELKIN is not set
|
||||||
# CONFIG_HID_CHERRY is not set
|
# CONFIG_HID_CHERRY is not set
|
||||||
# CONFIG_HID_CHICONY is not set
|
|
||||||
# CONFIG_HID_COUGAR is not set
|
# CONFIG_HID_COUGAR is not set
|
||||||
# CONFIG_HID_MACALLY is not set
|
# CONFIG_HID_MACALLY is not set
|
||||||
# CONFIG_HID_CMEDIA is not set
|
# CONFIG_HID_CMEDIA is not set
|
||||||
@@ -1879,7 +1938,6 @@ CONFIG_HID_REDRAGON=y
|
|||||||
# CONFIG_HID_PLAYSTATION is not set
|
# CONFIG_HID_PLAYSTATION is not set
|
||||||
# CONFIG_HID_PRIMAX is not set
|
# CONFIG_HID_PRIMAX is not set
|
||||||
# CONFIG_HID_SAITEK is not set
|
# CONFIG_HID_SAITEK is not set
|
||||||
# CONFIG_HID_SAMSUNG is not set
|
|
||||||
# CONFIG_HID_SEMITEK is not set
|
# CONFIG_HID_SEMITEK is not set
|
||||||
# CONFIG_HID_SPEEDLINK is not set
|
# CONFIG_HID_SPEEDLINK is not set
|
||||||
# CONFIG_HID_STEAM is not set
|
# CONFIG_HID_STEAM is not set
|
||||||
@@ -2011,8 +2069,6 @@ CONFIG_DMA_OF=y
|
|||||||
# DMABUF options
|
# DMABUF options
|
||||||
#
|
#
|
||||||
# CONFIG_SYNC_FILE is not set
|
# CONFIG_SYNC_FILE is not set
|
||||||
# CONFIG_DMABUF_MOVE_NOTIFY is not set
|
|
||||||
# CONFIG_DMABUF_DEBUG is not set
|
|
||||||
# CONFIG_DMABUF_HEAPS is not set
|
# CONFIG_DMABUF_HEAPS is not set
|
||||||
# end of DMABUF options
|
# end of DMABUF options
|
||||||
|
|
||||||
@@ -2027,13 +2083,14 @@ CONFIG_UIO_DMEM_GENIRQ=y
|
|||||||
# CONFIG_UIO_NETX is not set
|
# CONFIG_UIO_NETX is not set
|
||||||
# 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_IOMMU_TYPE1=y
|
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||||
CONFIG_VFIO_VIRQFD=y
|
CONFIG_VFIO_VIRQFD=y
|
||||||
CONFIG_VFIO=y
|
|
||||||
# CONFIG_VFIO_NOIOMMU is not set
|
# CONFIG_VFIO_NOIOMMU is not set
|
||||||
CONFIG_VFIO_PCI=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
|
||||||
|
CONFIG_VFIO_PCI=y
|
||||||
# CONFIG_VFIO_PLATFORM is not set
|
# CONFIG_VFIO_PLATFORM is not set
|
||||||
# CONFIG_VFIO_MDEV is not set
|
# CONFIG_VFIO_MDEV is not set
|
||||||
# CONFIG_VIRT_DRIVERS is not set
|
# CONFIG_VIRT_DRIVERS is not set
|
||||||
@@ -2057,6 +2114,7 @@ CONFIG_VHOST_MENU=y
|
|||||||
#
|
#
|
||||||
# Microsoft Hyper-V guest support
|
# Microsoft Hyper-V guest support
|
||||||
#
|
#
|
||||||
|
# CONFIG_HYPERV is not set
|
||||||
# end of Microsoft Hyper-V guest support
|
# end of Microsoft Hyper-V guest support
|
||||||
|
|
||||||
# CONFIG_GREYBUS is not set
|
# CONFIG_GREYBUS is not set
|
||||||
@@ -2118,6 +2176,8 @@ CONFIG_IOMMU_SUPPORT=y
|
|||||||
# end of Generic IOMMU Pagetable Support
|
# end of Generic IOMMU Pagetable Support
|
||||||
|
|
||||||
# CONFIG_IOMMU_DEBUGFS is not set
|
# CONFIG_IOMMU_DEBUGFS is not set
|
||||||
|
CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
|
||||||
|
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
|
||||||
# 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
|
||||||
@@ -2320,7 +2380,6 @@ CONFIG_FS_POSIX_ACL=y
|
|||||||
CONFIG_EXPORTFS=y
|
CONFIG_EXPORTFS=y
|
||||||
# CONFIG_EXPORTFS_BLOCK_OPS is not set
|
# CONFIG_EXPORTFS_BLOCK_OPS is not set
|
||||||
CONFIG_FILE_LOCKING=y
|
CONFIG_FILE_LOCKING=y
|
||||||
CONFIG_MANDATORY_FILE_LOCKING=y
|
|
||||||
CONFIG_FS_ENCRYPTION=y
|
CONFIG_FS_ENCRYPTION=y
|
||||||
CONFIG_FS_ENCRYPTION_ALGS=y
|
CONFIG_FS_ENCRYPTION_ALGS=y
|
||||||
# CONFIG_FS_VERITY is not set
|
# CONFIG_FS_VERITY is not set
|
||||||
@@ -2349,12 +2408,9 @@ CONFIG_NETFS_SUPPORT=y
|
|||||||
# CONFIG_NETFS_STATS is not set
|
# CONFIG_NETFS_STATS is not set
|
||||||
CONFIG_FSCACHE=y
|
CONFIG_FSCACHE=y
|
||||||
# CONFIG_FSCACHE_STATS is not set
|
# CONFIG_FSCACHE_STATS is not set
|
||||||
# CONFIG_FSCACHE_HISTOGRAM is not set
|
|
||||||
# CONFIG_FSCACHE_DEBUG is not set
|
# CONFIG_FSCACHE_DEBUG is not set
|
||||||
# CONFIG_FSCACHE_OBJECT_LIST is not set
|
|
||||||
CONFIG_CACHEFILES=y
|
CONFIG_CACHEFILES=y
|
||||||
# CONFIG_CACHEFILES_DEBUG is not set
|
# CONFIG_CACHEFILES_DEBUG is not set
|
||||||
# CONFIG_CACHEFILES_HISTOGRAM is not set
|
|
||||||
# end of Caches
|
# end of Caches
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -2375,6 +2431,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
|
|||||||
# CONFIG_FAT_DEFAULT_UTF8 is not set
|
# CONFIG_FAT_DEFAULT_UTF8 is not set
|
||||||
# CONFIG_EXFAT_FS is not set
|
# CONFIG_EXFAT_FS is not set
|
||||||
# CONFIG_NTFS_FS is not set
|
# CONFIG_NTFS_FS is not set
|
||||||
|
# CONFIG_NTFS3_FS is not set
|
||||||
# end of DOS/FAT/EXFAT/NT Filesystems
|
# end of DOS/FAT/EXFAT/NT Filesystems
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -2772,6 +2829,7 @@ CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
|
|||||||
CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y
|
CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y
|
||||||
CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y
|
CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y
|
||||||
CONFIG_SWIOTLB=y
|
CONFIG_SWIOTLB=y
|
||||||
|
# CONFIG_DMA_RESTRICTED_POOL is not set
|
||||||
CONFIG_DMA_NONCOHERENT_MMAP=y
|
CONFIG_DMA_NONCOHERENT_MMAP=y
|
||||||
CONFIG_DMA_COHERENT_POOL=y
|
CONFIG_DMA_COHERENT_POOL=y
|
||||||
CONFIG_DMA_REMAP=y
|
CONFIG_DMA_REMAP=y
|
||||||
@@ -2884,8 +2942,11 @@ CONFIG_DEBUG_MEMORY_INIT=y
|
|||||||
# CONFIG_DEBUG_PER_CPU_MAPS is not set
|
# CONFIG_DEBUG_PER_CPU_MAPS is not set
|
||||||
CONFIG_HAVE_ARCH_KASAN=y
|
CONFIG_HAVE_ARCH_KASAN=y
|
||||||
CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
|
CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
|
||||||
|
CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y
|
||||||
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
|
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
|
||||||
CONFIG_CC_HAS_KASAN_GENERIC=y
|
CONFIG_CC_HAS_KASAN_GENERIC=y
|
||||||
|
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
|
||||||
|
# CONFIG_KASAN is not set
|
||||||
CONFIG_HAVE_ARCH_KFENCE=y
|
CONFIG_HAVE_ARCH_KFENCE=y
|
||||||
# CONFIG_KFENCE is not set
|
# CONFIG_KFENCE is not set
|
||||||
# end of Memory Debugging
|
# end of Memory Debugging
|
||||||
@@ -2962,12 +3023,12 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=59
|
|||||||
# end of RCU Debugging
|
# end of RCU Debugging
|
||||||
|
|
||||||
# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
|
# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
|
||||||
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
|
|
||||||
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
|
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
|
||||||
# CONFIG_LATENCYTOP is not set
|
# CONFIG_LATENCYTOP is not set
|
||||||
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_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
|
||||||
@@ -2996,7 +3057,6 @@ CONFIG_CC_HAS_SANCOV_TRACE_PC=y
|
|||||||
CONFIG_RUNTIME_TESTING_MENU=y
|
CONFIG_RUNTIME_TESTING_MENU=y
|
||||||
# CONFIG_LKDTM is not set
|
# CONFIG_LKDTM is not set
|
||||||
# CONFIG_TEST_MIN_HEAP is not set
|
# CONFIG_TEST_MIN_HEAP is not set
|
||||||
# CONFIG_TEST_SORT is not set
|
|
||||||
# CONFIG_TEST_DIV64 is not set
|
# CONFIG_TEST_DIV64 is not set
|
||||||
# CONFIG_BACKTRACE_SELF_TEST is not set
|
# CONFIG_BACKTRACE_SELF_TEST is not set
|
||||||
# CONFIG_RBTREE_TEST is not set
|
# CONFIG_RBTREE_TEST is not set
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Linux/x86 5.14.0 Kernel Configuration
|
# Linux/x86 5.15.12 Kernel Configuration
|
||||||
#
|
#
|
||||||
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 10.3.0-1ubuntu1) 10.3.0"
|
CONFIG_CC_VERSION_TEXT="gcc (GCC) 11.2.1 20211203 (Red Hat 11.2.1-7)"
|
||||||
CONFIG_CC_IS_GCC=y
|
CONFIG_CC_IS_GCC=y
|
||||||
CONFIG_GCC_VERSION=100300
|
CONFIG_GCC_VERSION=110201
|
||||||
CONFIG_CLANG_VERSION=0
|
CONFIG_CLANG_VERSION=0
|
||||||
CONFIG_AS_IS_GNU=y
|
CONFIG_AS_IS_GNU=y
|
||||||
CONFIG_AS_VERSION=23500
|
CONFIG_AS_VERSION=23700
|
||||||
CONFIG_LD_IS_BFD=y
|
CONFIG_LD_IS_BFD=y
|
||||||
CONFIG_LD_VERSION=23500
|
CONFIG_LD_VERSION=23700
|
||||||
CONFIG_LLD_VERSION=0
|
CONFIG_LLD_VERSION=0
|
||||||
CONFIG_CC_CAN_LINK=y
|
CONFIG_CC_CAN_LINK=y
|
||||||
CONFIG_CC_CAN_LINK_STATIC=y
|
|
||||||
CONFIG_CC_HAS_ASM_GOTO=y
|
CONFIG_CC_HAS_ASM_GOTO=y
|
||||||
|
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||||
CONFIG_CC_HAS_ASM_INLINE=y
|
CONFIG_CC_HAS_ASM_INLINE=y
|
||||||
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
|
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
|
||||||
CONFIG_IRQ_WORK=y
|
CONFIG_IRQ_WORK=y
|
||||||
@@ -25,6 +25,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
|
|||||||
#
|
#
|
||||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||||
# CONFIG_COMPILE_TEST is not set
|
# CONFIG_COMPILE_TEST is not set
|
||||||
|
# CONFIG_WERROR is not set
|
||||||
CONFIG_LOCALVERSION=""
|
CONFIG_LOCALVERSION=""
|
||||||
# CONFIG_LOCALVERSION_AUTO is not set
|
# CONFIG_LOCALVERSION_AUTO is not set
|
||||||
CONFIG_BUILD_SALT=""
|
CONFIG_BUILD_SALT=""
|
||||||
@@ -154,6 +155,7 @@ CONFIG_BUILD_BIN2C=y
|
|||||||
CONFIG_LOG_BUF_SHIFT=21
|
CONFIG_LOG_BUF_SHIFT=21
|
||||||
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
|
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
|
||||||
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
|
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
|
||||||
|
# CONFIG_PRINTK_INDEX is not set
|
||||||
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
|
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -226,7 +228,6 @@ CONFIG_SYSFS_SYSCALL=y
|
|||||||
CONFIG_FHANDLE=y
|
CONFIG_FHANDLE=y
|
||||||
CONFIG_POSIX_TIMERS=y
|
CONFIG_POSIX_TIMERS=y
|
||||||
CONFIG_PRINTK=y
|
CONFIG_PRINTK=y
|
||||||
CONFIG_PRINTK_NMI=y
|
|
||||||
CONFIG_BUG=y
|
CONFIG_BUG=y
|
||||||
CONFIG_ELF_CORE=y
|
CONFIG_ELF_CORE=y
|
||||||
CONFIG_PCSPKR_PLATFORM=y
|
CONFIG_PCSPKR_PLATFORM=y
|
||||||
@@ -299,6 +300,7 @@ CONFIG_HAVE_SETUP_PER_CPU_AREA=y
|
|||||||
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
|
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
|
||||||
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
|
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=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_ARCH_WANT_GENERAL_HUGETLB=y
|
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
|
||||||
CONFIG_AUDIT_ARCH=y
|
CONFIG_AUDIT_ARCH=y
|
||||||
@@ -380,13 +382,13 @@ CONFIG_PERF_EVENTS_INTEL_UNCORE=y
|
|||||||
CONFIG_PERF_EVENTS_INTEL_RAPL=y
|
CONFIG_PERF_EVENTS_INTEL_RAPL=y
|
||||||
CONFIG_PERF_EVENTS_INTEL_CSTATE=y
|
CONFIG_PERF_EVENTS_INTEL_CSTATE=y
|
||||||
# CONFIG_PERF_EVENTS_AMD_POWER is not set
|
# CONFIG_PERF_EVENTS_AMD_POWER is not set
|
||||||
|
CONFIG_PERF_EVENTS_AMD_UNCORE=y
|
||||||
# end of Performance monitoring
|
# end of Performance monitoring
|
||||||
|
|
||||||
CONFIG_X86_16BIT=y
|
CONFIG_X86_16BIT=y
|
||||||
CONFIG_X86_ESPFIX64=y
|
CONFIG_X86_ESPFIX64=y
|
||||||
CONFIG_X86_VSYSCALL_EMULATION=y
|
CONFIG_X86_VSYSCALL_EMULATION=y
|
||||||
# CONFIG_X86_IOPL_IOPERM is not set
|
# CONFIG_X86_IOPL_IOPERM is not set
|
||||||
# CONFIG_I8K is not set
|
|
||||||
# CONFIG_MICROCODE is not set
|
# CONFIG_MICROCODE is not set
|
||||||
CONFIG_X86_MSR=y
|
CONFIG_X86_MSR=y
|
||||||
CONFIG_X86_CPUID=y
|
CONFIG_X86_CPUID=y
|
||||||
@@ -585,7 +587,6 @@ CONFIG_MMCONF_FAM10H=y
|
|||||||
# CONFIG_ISA_BUS is not set
|
# CONFIG_ISA_BUS is not set
|
||||||
# CONFIG_ISA_DMA_API is not set
|
# CONFIG_ISA_DMA_API is not set
|
||||||
CONFIG_AMD_NB=y
|
CONFIG_AMD_NB=y
|
||||||
# CONFIG_X86_SYSFB is not set
|
|
||||||
# end of Bus options (PCI etc.)
|
# end of Bus options (PCI etc.)
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -595,44 +596,6 @@ CONFIG_AMD_NB=y
|
|||||||
# CONFIG_X86_X32 is not set
|
# CONFIG_X86_X32 is not set
|
||||||
# end of Binary Emulations
|
# end of Binary Emulations
|
||||||
|
|
||||||
#
|
|
||||||
# Firmware Drivers
|
|
||||||
#
|
|
||||||
# CONFIG_EDD is not set
|
|
||||||
CONFIG_FIRMWARE_MEMMAP=y
|
|
||||||
CONFIG_DMIID=y
|
|
||||||
CONFIG_DMI_SYSFS=y
|
|
||||||
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
|
|
||||||
# CONFIG_FW_CFG_SYSFS is not set
|
|
||||||
# CONFIG_GOOGLE_FIRMWARE is not set
|
|
||||||
|
|
||||||
#
|
|
||||||
# EFI (Extensible Firmware Interface) Support
|
|
||||||
#
|
|
||||||
# CONFIG_EFI_VARS is not set
|
|
||||||
CONFIG_EFI_ESRT=y
|
|
||||||
CONFIG_EFI_RUNTIME_MAP=y
|
|
||||||
# CONFIG_EFI_FAKE_MEMMAP is not set
|
|
||||||
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
|
||||||
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
|
||||||
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
|
||||||
# CONFIG_EFI_CAPSULE_LOADER is not set
|
|
||||||
# CONFIG_EFI_TEST is not set
|
|
||||||
# CONFIG_APPLE_PROPERTIES is not set
|
|
||||||
# CONFIG_RESET_ATTACK_MITIGATION is not set
|
|
||||||
# CONFIG_EFI_RCI2_TABLE is not set
|
|
||||||
# CONFIG_EFI_DISABLE_PCI_DMA is not set
|
|
||||||
# end of EFI (Extensible Firmware Interface) Support
|
|
||||||
|
|
||||||
CONFIG_EFI_EARLYCON=y
|
|
||||||
# CONFIG_EFI_CUSTOM_SSDT_OVERLAYS is not set
|
|
||||||
|
|
||||||
#
|
|
||||||
# Tegra firmware driver
|
|
||||||
#
|
|
||||||
# end of Tegra firmware driver
|
|
||||||
# end of Firmware Drivers
|
|
||||||
|
|
||||||
CONFIG_HAVE_KVM=y
|
CONFIG_HAVE_KVM=y
|
||||||
CONFIG_HAVE_KVM_IRQCHIP=y
|
CONFIG_HAVE_KVM_IRQCHIP=y
|
||||||
CONFIG_HAVE_KVM_IRQFD=y
|
CONFIG_HAVE_KVM_IRQFD=y
|
||||||
@@ -679,6 +642,7 @@ CONFIG_HAVE_OPTPROBES=y
|
|||||||
CONFIG_HAVE_KPROBES_ON_FTRACE=y
|
CONFIG_HAVE_KPROBES_ON_FTRACE=y
|
||||||
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
|
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
|
||||||
CONFIG_HAVE_NMI=y
|
CONFIG_HAVE_NMI=y
|
||||||
|
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||||
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
||||||
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
||||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||||
@@ -753,12 +717,14 @@ CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
|
|||||||
CONFIG_ARCH_USE_MEMREMAP_PROT=y
|
CONFIG_ARCH_USE_MEMREMAP_PROT=y
|
||||||
# CONFIG_LOCK_EVENT_COUNTS is not set
|
# CONFIG_LOCK_EVENT_COUNTS is not set
|
||||||
CONFIG_ARCH_HAS_MEM_ENCRYPT=y
|
CONFIG_ARCH_HAS_MEM_ENCRYPT=y
|
||||||
|
CONFIG_ARCH_HAS_CC_PLATFORM=y
|
||||||
CONFIG_HAVE_STATIC_CALL=y
|
CONFIG_HAVE_STATIC_CALL=y
|
||||||
CONFIG_HAVE_STATIC_CALL_INLINE=y
|
CONFIG_HAVE_STATIC_CALL_INLINE=y
|
||||||
CONFIG_HAVE_PREEMPT_DYNAMIC=y
|
CONFIG_HAVE_PREEMPT_DYNAMIC=y
|
||||||
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
|
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
|
||||||
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
|
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
|
||||||
CONFIG_ARCH_HAS_ELFCORE_COMPAT=y
|
CONFIG_ARCH_HAS_ELFCORE_COMPAT=y
|
||||||
|
CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# GCOV-based kernel profiling
|
# GCOV-based kernel profiling
|
||||||
@@ -775,16 +741,14 @@ CONFIG_BASE_SMALL=0
|
|||||||
# CONFIG_MODULES is not set
|
# CONFIG_MODULES is not set
|
||||||
CONFIG_MODULES_TREE_LOOKUP=y
|
CONFIG_MODULES_TREE_LOOKUP=y
|
||||||
CONFIG_BLOCK=y
|
CONFIG_BLOCK=y
|
||||||
CONFIG_BLK_SCSI_REQUEST=y
|
|
||||||
CONFIG_BLK_CGROUP_RWSTAT=y
|
CONFIG_BLK_CGROUP_RWSTAT=y
|
||||||
CONFIG_BLK_DEV_BSG=y
|
CONFIG_BLK_DEV_BSG_COMMON=y
|
||||||
CONFIG_BLK_DEV_BSGLIB=y
|
CONFIG_BLK_DEV_BSGLIB=y
|
||||||
CONFIG_BLK_DEV_INTEGRITY=y
|
CONFIG_BLK_DEV_INTEGRITY=y
|
||||||
CONFIG_BLK_DEV_INTEGRITY_T10=y
|
CONFIG_BLK_DEV_INTEGRITY_T10=y
|
||||||
# CONFIG_BLK_DEV_ZONED is not set
|
# CONFIG_BLK_DEV_ZONED is not set
|
||||||
CONFIG_BLK_DEV_THROTTLING=y
|
CONFIG_BLK_DEV_THROTTLING=y
|
||||||
# CONFIG_BLK_DEV_THROTTLING_LOW is not set
|
# CONFIG_BLK_DEV_THROTTLING_LOW is not set
|
||||||
CONFIG_BLK_CMDLINE_PARSER=y
|
|
||||||
CONFIG_BLK_WBT=y
|
CONFIG_BLK_WBT=y
|
||||||
CONFIG_BLK_WBT_MQ=y
|
CONFIG_BLK_WBT_MQ=y
|
||||||
# CONFIG_BLK_CGROUP_IOLATENCY is not set
|
# CONFIG_BLK_CGROUP_IOLATENCY is not set
|
||||||
@@ -818,6 +782,7 @@ CONFIG_EFI_PARTITION=y
|
|||||||
CONFIG_BLK_MQ_PCI=y
|
CONFIG_BLK_MQ_PCI=y
|
||||||
CONFIG_BLK_MQ_VIRTIO=y
|
CONFIG_BLK_MQ_VIRTIO=y
|
||||||
CONFIG_BLK_PM=y
|
CONFIG_BLK_PM=y
|
||||||
|
CONFIG_BLOCK_HOLDER_DEPRECATED=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# IO Schedulers
|
# IO Schedulers
|
||||||
@@ -934,6 +899,12 @@ CONFIG_PERCPU_STATS=y
|
|||||||
# CONFIG_READ_ONLY_THP_FOR_FS is not set
|
# CONFIG_READ_ONLY_THP_FOR_FS is not set
|
||||||
CONFIG_ARCH_HAS_PTE_SPECIAL=y
|
CONFIG_ARCH_HAS_PTE_SPECIAL=y
|
||||||
CONFIG_SECRETMEM=y
|
CONFIG_SECRETMEM=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Data Access Monitoring
|
||||||
|
#
|
||||||
|
# CONFIG_DAMON is not set
|
||||||
|
# end of Data Access Monitoring
|
||||||
# end of Memory Management options
|
# end of Memory Management options
|
||||||
|
|
||||||
CONFIG_NET=y
|
CONFIG_NET=y
|
||||||
@@ -946,6 +917,7 @@ CONFIG_PACKET=y
|
|||||||
CONFIG_PACKET_DIAG=y
|
CONFIG_PACKET_DIAG=y
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
CONFIG_UNIX_SCM=y
|
CONFIG_UNIX_SCM=y
|
||||||
|
CONFIG_AF_UNIX_OOB=y
|
||||||
CONFIG_UNIX_DIAG=y
|
CONFIG_UNIX_DIAG=y
|
||||||
CONFIG_TLS=y
|
CONFIG_TLS=y
|
||||||
# CONFIG_TLS_DEVICE is not set
|
# CONFIG_TLS_DEVICE is not set
|
||||||
@@ -1050,6 +1022,7 @@ CONFIG_NET_FLOW_LIMIT=y
|
|||||||
# CONFIG_AF_RXRPC is not set
|
# CONFIG_AF_RXRPC is not set
|
||||||
# CONFIG_AF_KCM is not set
|
# CONFIG_AF_KCM is not set
|
||||||
CONFIG_STREAM_PARSER=y
|
CONFIG_STREAM_PARSER=y
|
||||||
|
# CONFIG_MCTP is not set
|
||||||
# CONFIG_WIRELESS is not set
|
# CONFIG_WIRELESS is not set
|
||||||
# CONFIG_RFKILL is not set
|
# CONFIG_RFKILL is not set
|
||||||
# CONFIG_NET_9P is not set
|
# CONFIG_NET_9P is not set
|
||||||
@@ -1186,6 +1159,53 @@ CONFIG_GENERIC_CPU_VULNERABILITIES=y
|
|||||||
|
|
||||||
CONFIG_CONNECTOR=y
|
CONFIG_CONNECTOR=y
|
||||||
CONFIG_PROC_EVENTS=y
|
CONFIG_PROC_EVENTS=y
|
||||||
|
|
||||||
|
#
|
||||||
|
# Firmware Drivers
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# ARM System Control and Management Interface Protocol
|
||||||
|
#
|
||||||
|
# end of ARM System Control and Management Interface Protocol
|
||||||
|
|
||||||
|
# CONFIG_EDD is not set
|
||||||
|
CONFIG_FIRMWARE_MEMMAP=y
|
||||||
|
CONFIG_DMIID=y
|
||||||
|
CONFIG_DMI_SYSFS=y
|
||||||
|
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
|
||||||
|
# CONFIG_FW_CFG_SYSFS is not set
|
||||||
|
CONFIG_SYSFB=y
|
||||||
|
# CONFIG_SYSFB_SIMPLEFB is not set
|
||||||
|
# CONFIG_GOOGLE_FIRMWARE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# EFI (Extensible Firmware Interface) Support
|
||||||
|
#
|
||||||
|
# CONFIG_EFI_VARS is not set
|
||||||
|
CONFIG_EFI_ESRT=y
|
||||||
|
CONFIG_EFI_RUNTIME_MAP=y
|
||||||
|
# CONFIG_EFI_FAKE_MEMMAP is not set
|
||||||
|
CONFIG_EFI_RUNTIME_WRAPPERS=y
|
||||||
|
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
||||||
|
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
|
||||||
|
# CONFIG_EFI_CAPSULE_LOADER is not set
|
||||||
|
# CONFIG_EFI_TEST is not set
|
||||||
|
# CONFIG_APPLE_PROPERTIES is not set
|
||||||
|
# CONFIG_RESET_ATTACK_MITIGATION is not set
|
||||||
|
# CONFIG_EFI_RCI2_TABLE is not set
|
||||||
|
# CONFIG_EFI_DISABLE_PCI_DMA is not set
|
||||||
|
# end of EFI (Extensible Firmware Interface) Support
|
||||||
|
|
||||||
|
CONFIG_EFI_EARLYCON=y
|
||||||
|
# CONFIG_EFI_CUSTOM_SSDT_OVERLAYS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tegra firmware driver
|
||||||
|
#
|
||||||
|
# end of Tegra firmware driver
|
||||||
|
# end of Firmware Drivers
|
||||||
|
|
||||||
# CONFIG_GNSS is not set
|
# CONFIG_GNSS is not set
|
||||||
# CONFIG_MTD is not set
|
# CONFIG_MTD is not set
|
||||||
# CONFIG_OF is not set
|
# CONFIG_OF is not set
|
||||||
@@ -1227,7 +1247,7 @@ CONFIG_VIRTIO_BLK=y
|
|||||||
#
|
#
|
||||||
CONFIG_NVME_CORE=y
|
CONFIG_NVME_CORE=y
|
||||||
CONFIG_BLK_DEV_NVME=y
|
CONFIG_BLK_DEV_NVME=y
|
||||||
# CONFIG_NVME_MULTIPATH is not set
|
CONFIG_NVME_MULTIPATH=y
|
||||||
# CONFIG_NVME_FC is not set
|
# CONFIG_NVME_FC is not set
|
||||||
# CONFIG_NVME_TCP is not set
|
# CONFIG_NVME_TCP is not set
|
||||||
# CONFIG_NVME_TARGET is not set
|
# CONFIG_NVME_TARGET is not set
|
||||||
@@ -1288,7 +1308,38 @@ CONFIG_SCSI_MOD=y
|
|||||||
# end of SCSI device support
|
# end of SCSI device support
|
||||||
|
|
||||||
# CONFIG_ATA is not set
|
# CONFIG_ATA is not set
|
||||||
# CONFIG_MD is not set
|
CONFIG_MD=y
|
||||||
|
# CONFIG_BLK_DEV_MD is not set
|
||||||
|
# CONFIG_BCACHE is not set
|
||||||
|
CONFIG_BLK_DEV_DM_BUILTIN=y
|
||||||
|
CONFIG_BLK_DEV_DM=y
|
||||||
|
# CONFIG_DM_DEBUG is not set
|
||||||
|
# CONFIG_DM_UNSTRIPED is not set
|
||||||
|
# CONFIG_DM_CRYPT is not set
|
||||||
|
# CONFIG_DM_SNAPSHOT is not set
|
||||||
|
# CONFIG_DM_THIN_PROVISIONING is not set
|
||||||
|
# CONFIG_DM_CACHE is not set
|
||||||
|
# CONFIG_DM_WRITECACHE is not set
|
||||||
|
# CONFIG_DM_EBS is not set
|
||||||
|
# CONFIG_DM_ERA is not set
|
||||||
|
# CONFIG_DM_CLONE is not set
|
||||||
|
# CONFIG_DM_MIRROR is not set
|
||||||
|
# CONFIG_DM_RAID is not set
|
||||||
|
# CONFIG_DM_ZERO is not set
|
||||||
|
CONFIG_DM_MULTIPATH=y
|
||||||
|
# CONFIG_DM_MULTIPATH_QL is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_ST is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_HST is not set
|
||||||
|
# CONFIG_DM_MULTIPATH_IOA is not set
|
||||||
|
# CONFIG_DM_DELAY is not set
|
||||||
|
# CONFIG_DM_DUST is not set
|
||||||
|
# CONFIG_DM_INIT is not set
|
||||||
|
# CONFIG_DM_UEVENT is not set
|
||||||
|
# CONFIG_DM_FLAKEY is not set
|
||||||
|
# CONFIG_DM_VERITY is not set
|
||||||
|
# CONFIG_DM_SWITCH is not set
|
||||||
|
# CONFIG_DM_LOG_WRITES is not set
|
||||||
|
# CONFIG_DM_INTEGRITY is not set
|
||||||
# CONFIG_TARGET_CORE is not set
|
# CONFIG_TARGET_CORE is not set
|
||||||
# CONFIG_FUSION is not set
|
# CONFIG_FUSION is not set
|
||||||
|
|
||||||
@@ -1354,7 +1405,6 @@ CONFIG_VIRTIO_NET=y
|
|||||||
# CONFIG_NETDEVSIM is not set
|
# CONFIG_NETDEVSIM is not set
|
||||||
CONFIG_NET_FAILOVER=y
|
CONFIG_NET_FAILOVER=y
|
||||||
# CONFIG_ISDN is not set
|
# CONFIG_ISDN is not set
|
||||||
# CONFIG_NVM is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Input device support
|
# Input device support
|
||||||
@@ -1503,10 +1553,9 @@ 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
|
||||||
# end of Character devices
|
|
||||||
|
|
||||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||||
|
# end of Character devices
|
||||||
|
|
||||||
#
|
#
|
||||||
# I2C support
|
# I2C support
|
||||||
@@ -1536,13 +1585,13 @@ CONFIG_PPS=y
|
|||||||
# PTP clock support
|
# PTP clock support
|
||||||
#
|
#
|
||||||
CONFIG_PTP_1588_CLOCK=y
|
CONFIG_PTP_1588_CLOCK=y
|
||||||
|
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
|
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
|
||||||
#
|
#
|
||||||
CONFIG_PTP_1588_CLOCK_KVM=y
|
CONFIG_PTP_1588_CLOCK_KVM=y
|
||||||
# CONFIG_PTP_1588_CLOCK_VMW is not set
|
# CONFIG_PTP_1588_CLOCK_VMW is not set
|
||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
@@ -1598,6 +1647,7 @@ CONFIG_GPIO_PCI_IDIO_16=y
|
|||||||
#
|
#
|
||||||
# CONFIG_GPIO_AGGREGATOR is not set
|
# CONFIG_GPIO_AGGREGATOR is not set
|
||||||
# CONFIG_GPIO_MOCKUP is not set
|
# CONFIG_GPIO_MOCKUP is not set
|
||||||
|
# CONFIG_GPIO_VIRTIO is not set
|
||||||
# end of Virtual GPIO drivers
|
# end of Virtual GPIO drivers
|
||||||
|
|
||||||
# CONFIG_W1 is not set
|
# CONFIG_W1 is not set
|
||||||
@@ -1634,6 +1684,7 @@ CONFIG_X86_THERMAL_VECTOR=y
|
|||||||
|
|
||||||
# CONFIG_INTEL_PCH_THERMAL is not set
|
# CONFIG_INTEL_PCH_THERMAL is not set
|
||||||
# CONFIG_INTEL_TCC_COOLING is not set
|
# CONFIG_INTEL_TCC_COOLING is not set
|
||||||
|
# CONFIG_INTEL_MENLOW is not set
|
||||||
# end of Intel thermal drivers
|
# end of Intel thermal drivers
|
||||||
|
|
||||||
CONFIG_WATCHDOG=y
|
CONFIG_WATCHDOG=y
|
||||||
@@ -1853,7 +1904,6 @@ CONFIG_HID_GENERIC=y
|
|||||||
# CONFIG_HID_AUREAL is not set
|
# CONFIG_HID_AUREAL is not set
|
||||||
# CONFIG_HID_BELKIN is not set
|
# CONFIG_HID_BELKIN is not set
|
||||||
# CONFIG_HID_CHERRY is not set
|
# CONFIG_HID_CHERRY is not set
|
||||||
# CONFIG_HID_CHICONY is not set
|
|
||||||
# CONFIG_HID_COUGAR is not set
|
# CONFIG_HID_COUGAR is not set
|
||||||
# CONFIG_HID_MACALLY is not set
|
# CONFIG_HID_MACALLY is not set
|
||||||
# CONFIG_HID_CMEDIA is not set
|
# CONFIG_HID_CMEDIA is not set
|
||||||
@@ -1894,7 +1944,6 @@ CONFIG_HID_REDRAGON=y
|
|||||||
# CONFIG_HID_PLAYSTATION is not set
|
# CONFIG_HID_PLAYSTATION is not set
|
||||||
# CONFIG_HID_PRIMAX is not set
|
# CONFIG_HID_PRIMAX is not set
|
||||||
# CONFIG_HID_SAITEK is not set
|
# CONFIG_HID_SAITEK is not set
|
||||||
# CONFIG_HID_SAMSUNG is not set
|
|
||||||
# CONFIG_HID_SEMITEK is not set
|
# CONFIG_HID_SEMITEK is not set
|
||||||
# CONFIG_HID_SPEEDLINK is not set
|
# CONFIG_HID_SPEEDLINK is not set
|
||||||
# CONFIG_HID_STEAM is not set
|
# CONFIG_HID_STEAM is not set
|
||||||
@@ -1951,9 +2000,10 @@ CONFIG_DMA_VIRTUAL_CHANNELS=y
|
|||||||
CONFIG_DMA_ACPI=y
|
CONFIG_DMA_ACPI=y
|
||||||
# CONFIG_ALTERA_MSGDMA is not set
|
# CONFIG_ALTERA_MSGDMA is not set
|
||||||
# CONFIG_INTEL_IDMA64 is not set
|
# CONFIG_INTEL_IDMA64 is not set
|
||||||
# CONFIG_INTEL_IDXD is not set
|
# CONFIG_INTEL_IDXD_COMPAT is not set
|
||||||
# CONFIG_INTEL_IOATDMA is not set
|
# CONFIG_INTEL_IOATDMA is not set
|
||||||
# CONFIG_PLX_DMA is not set
|
# CONFIG_PLX_DMA is not set
|
||||||
|
# CONFIG_AMD_PTDMA is not set
|
||||||
# CONFIG_QCOM_HIDMA_MGMT is not set
|
# CONFIG_QCOM_HIDMA_MGMT is not set
|
||||||
# CONFIG_QCOM_HIDMA is not set
|
# CONFIG_QCOM_HIDMA is not set
|
||||||
CONFIG_DW_DMAC_CORE=y
|
CONFIG_DW_DMAC_CORE=y
|
||||||
@@ -1975,8 +2025,6 @@ CONFIG_HSU_DMA=y
|
|||||||
# DMABUF options
|
# DMABUF options
|
||||||
#
|
#
|
||||||
# CONFIG_SYNC_FILE is not set
|
# CONFIG_SYNC_FILE is not set
|
||||||
# CONFIG_DMABUF_MOVE_NOTIFY is not set
|
|
||||||
# CONFIG_DMABUF_DEBUG is not set
|
|
||||||
# CONFIG_DMABUF_HEAPS is not set
|
# CONFIG_DMABUF_HEAPS is not set
|
||||||
# end of DMABUF options
|
# end of DMABUF options
|
||||||
|
|
||||||
@@ -1992,14 +2040,15 @@ 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_UIO_HV_GENERIC is not set
|
# CONFIG_UIO_HV_GENERIC is not set
|
||||||
|
CONFIG_VFIO=y
|
||||||
CONFIG_VFIO_IOMMU_TYPE1=y
|
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||||
CONFIG_VFIO_VIRQFD=y
|
CONFIG_VFIO_VIRQFD=y
|
||||||
CONFIG_VFIO=y
|
|
||||||
# CONFIG_VFIO_NOIOMMU is not set
|
# CONFIG_VFIO_NOIOMMU is not set
|
||||||
CONFIG_VFIO_PCI=y
|
CONFIG_VFIO_PCI_CORE=y
|
||||||
# CONFIG_VFIO_PCI_VGA is not set
|
|
||||||
CONFIG_VFIO_PCI_MMAP=y
|
CONFIG_VFIO_PCI_MMAP=y
|
||||||
CONFIG_VFIO_PCI_INTX=y
|
CONFIG_VFIO_PCI_INTX=y
|
||||||
|
CONFIG_VFIO_PCI=y
|
||||||
|
# CONFIG_VFIO_PCI_VGA is not set
|
||||||
# CONFIG_VFIO_PCI_IGD is not set
|
# CONFIG_VFIO_PCI_IGD is not set
|
||||||
# CONFIG_VFIO_MDEV is not set
|
# CONFIG_VFIO_MDEV is not set
|
||||||
CONFIG_IRQ_BYPASS_MANAGER=y
|
CONFIG_IRQ_BYPASS_MANAGER=y
|
||||||
@@ -2071,6 +2120,8 @@ CONFIG_IOMMU_SUPPORT=y
|
|||||||
# end of Generic IOMMU Pagetable Support
|
# end of Generic IOMMU Pagetable Support
|
||||||
|
|
||||||
# CONFIG_IOMMU_DEBUGFS is not set
|
# CONFIG_IOMMU_DEBUGFS is not set
|
||||||
|
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
|
||||||
|
CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
|
||||||
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
||||||
CONFIG_IOMMU_DMA=y
|
CONFIG_IOMMU_DMA=y
|
||||||
# CONFIG_AMD_IOMMU is not set
|
# CONFIG_AMD_IOMMU is not set
|
||||||
@@ -2241,7 +2292,6 @@ CONFIG_FS_POSIX_ACL=y
|
|||||||
CONFIG_EXPORTFS=y
|
CONFIG_EXPORTFS=y
|
||||||
# CONFIG_EXPORTFS_BLOCK_OPS is not set
|
# CONFIG_EXPORTFS_BLOCK_OPS is not set
|
||||||
CONFIG_FILE_LOCKING=y
|
CONFIG_FILE_LOCKING=y
|
||||||
CONFIG_MANDATORY_FILE_LOCKING=y
|
|
||||||
CONFIG_FS_ENCRYPTION=y
|
CONFIG_FS_ENCRYPTION=y
|
||||||
CONFIG_FS_ENCRYPTION_ALGS=y
|
CONFIG_FS_ENCRYPTION_ALGS=y
|
||||||
# CONFIG_FS_VERITY is not set
|
# CONFIG_FS_VERITY is not set
|
||||||
@@ -2270,12 +2320,9 @@ CONFIG_NETFS_SUPPORT=y
|
|||||||
# CONFIG_NETFS_STATS is not set
|
# CONFIG_NETFS_STATS is not set
|
||||||
CONFIG_FSCACHE=y
|
CONFIG_FSCACHE=y
|
||||||
# CONFIG_FSCACHE_STATS is not set
|
# CONFIG_FSCACHE_STATS is not set
|
||||||
# CONFIG_FSCACHE_HISTOGRAM is not set
|
|
||||||
# CONFIG_FSCACHE_DEBUG is not set
|
# CONFIG_FSCACHE_DEBUG is not set
|
||||||
# CONFIG_FSCACHE_OBJECT_LIST is not set
|
|
||||||
CONFIG_CACHEFILES=y
|
CONFIG_CACHEFILES=y
|
||||||
# CONFIG_CACHEFILES_DEBUG is not set
|
# CONFIG_CACHEFILES_DEBUG is not set
|
||||||
# CONFIG_CACHEFILES_HISTOGRAM is not set
|
|
||||||
# end of Caches
|
# end of Caches
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -2296,6 +2343,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
|
|||||||
# CONFIG_FAT_DEFAULT_UTF8 is not set
|
# CONFIG_FAT_DEFAULT_UTF8 is not set
|
||||||
# CONFIG_EXFAT_FS is not set
|
# CONFIG_EXFAT_FS is not set
|
||||||
# CONFIG_NTFS_FS is not set
|
# CONFIG_NTFS_FS is not set
|
||||||
|
# CONFIG_NTFS3_FS is not set
|
||||||
# end of DOS/FAT/EXFAT/NT Filesystems
|
# end of DOS/FAT/EXFAT/NT Filesystems
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -2411,6 +2459,8 @@ CONFIG_LSM="yama,loadpin,safesetid,integrity"
|
|||||||
CONFIG_INIT_STACK_NONE=y
|
CONFIG_INIT_STACK_NONE=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_ZERO_CALL_USED_REGS is not set
|
||||||
# end of Memory initialization
|
# end of Memory initialization
|
||||||
# end of Kernel hardening options
|
# end of Kernel hardening options
|
||||||
# end of Security options
|
# end of Security options
|
||||||
@@ -2556,6 +2606,8 @@ CONFIG_CRYPTO_DES=y
|
|||||||
# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set
|
# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set
|
||||||
# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set
|
# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set
|
||||||
# CONFIG_CRYPTO_SM4 is not set
|
# CONFIG_CRYPTO_SM4 is not set
|
||||||
|
# CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64 is not set
|
||||||
|
# CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64 is not set
|
||||||
# CONFIG_CRYPTO_TWOFISH is not set
|
# CONFIG_CRYPTO_TWOFISH is not set
|
||||||
CONFIG_CRYPTO_TWOFISH_COMMON=y
|
CONFIG_CRYPTO_TWOFISH_COMMON=y
|
||||||
CONFIG_CRYPTO_TWOFISH_X86_64=y
|
CONFIG_CRYPTO_TWOFISH_X86_64=y
|
||||||
@@ -2761,6 +2813,8 @@ CONFIG_HAVE_ARCH_KGDB=y
|
|||||||
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
|
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
|
||||||
# CONFIG_UBSAN is not set
|
# CONFIG_UBSAN is not set
|
||||||
CONFIG_HAVE_ARCH_KCSAN=y
|
CONFIG_HAVE_ARCH_KCSAN=y
|
||||||
|
CONFIG_HAVE_KCSAN_COMPILER=y
|
||||||
|
# CONFIG_KCSAN is not set
|
||||||
# end of Generic Kernel Debugging Instruments
|
# end of Generic Kernel Debugging Instruments
|
||||||
|
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
@@ -2877,7 +2931,6 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=59
|
|||||||
# end of RCU Debugging
|
# end of RCU Debugging
|
||||||
|
|
||||||
# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
|
# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
|
||||||
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
|
|
||||||
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
|
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
|
||||||
# CONFIG_LATENCYTOP is not set
|
# CONFIG_LATENCYTOP is not set
|
||||||
CONFIG_USER_STACKTRACE_SUPPORT=y
|
CONFIG_USER_STACKTRACE_SUPPORT=y
|
||||||
@@ -2903,7 +2956,6 @@ CONFIG_STRICT_DEVMEM=y
|
|||||||
#
|
#
|
||||||
# x86 Debugging
|
# x86 Debugging
|
||||||
#
|
#
|
||||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
|
||||||
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
|
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
|
||||||
CONFIG_X86_VERBOSE_BOOTUP=y
|
CONFIG_X86_VERBOSE_BOOTUP=y
|
||||||
CONFIG_EARLY_PRINTK=y
|
CONFIG_EARLY_PRINTK=y
|
||||||
@@ -2940,7 +2992,6 @@ CONFIG_CC_HAS_SANCOV_TRACE_PC=y
|
|||||||
CONFIG_RUNTIME_TESTING_MENU=y
|
CONFIG_RUNTIME_TESTING_MENU=y
|
||||||
# CONFIG_LKDTM is not set
|
# CONFIG_LKDTM is not set
|
||||||
# CONFIG_TEST_MIN_HEAP is not set
|
# CONFIG_TEST_MIN_HEAP is not set
|
||||||
# CONFIG_TEST_SORT is not set
|
|
||||||
# CONFIG_TEST_DIV64 is not set
|
# CONFIG_TEST_DIV64 is not set
|
||||||
# CONFIG_BACKTRACE_SELF_TEST is not set
|
# CONFIG_BACKTRACE_SELF_TEST is not set
|
||||||
# CONFIG_RBTREE_TEST is not set
|
# CONFIG_RBTREE_TEST is not set
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
|
# This spec file assumes you're building on an environment where:
|
||||||
|
# * You have access to the internet during the build
|
||||||
|
# * You have rustup installed on your system
|
||||||
|
# * You have both x86_64-unknown-linux-gnu and x86_64-unknown-linux-musl
|
||||||
|
# targets installed.
|
||||||
|
|
||||||
|
%define using_rustup 1
|
||||||
|
%define using_musl_libc 1
|
||||||
|
|
||||||
Name: cloud-hypervisor
|
Name: cloud-hypervisor
|
||||||
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
||||||
Version: 18.0
|
Version: 21.1
|
||||||
Release: 0%{?dist}
|
Release: 0%{?dist}
|
||||||
License: ASL 2.0 or BSD-3-clause
|
License: ASL 2.0 or BSD-3-clause
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
@@ -12,7 +21,7 @@ BuildRequires: glibc-devel
|
|||||||
BuildRequires: binutils
|
BuildRequires: binutils
|
||||||
BuildRequires: git
|
BuildRequires: git
|
||||||
|
|
||||||
%if 0%{?fedora} || 0%{?rhel}
|
%if ! 0%{?using_rustup}
|
||||||
BuildRequires: rust
|
BuildRequires: rust
|
||||||
BuildRequires: cargo
|
BuildRequires: cargo
|
||||||
%endif
|
%endif
|
||||||
@@ -39,11 +48,13 @@ install -d %{buildroot}%{_libdir}/cloud-hypervisor
|
|||||||
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor
|
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor
|
||||||
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor
|
install -D -m755 target/x86_64-unknown-linux-gnu/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor
|
||||||
|
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
install -d %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -d %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/cloud-hypervisor %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/x86_64-unknown-linux-musl/release/cloud-hypervisor %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_block %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/x86_64-unknown-linux-musl/release/vhost_user_net %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
install -D -m755 target/x86_64-unknown-linux-musl/release/ch-remote %{buildroot}%{_libdir}/cloud-hypervisor/static
|
install -D -m755 target/x86_64-unknown-linux-musl/release/ch-remote %{buildroot}%{_libdir}/cloud-hypervisor/static
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
@@ -52,22 +63,33 @@ if [[ $? -ne 0 ]]; then
|
|||||||
echo "Cargo not found, please install cargo. exiting"
|
echo "Cargo not found, please install cargo. exiting"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
%if 0%{?using_rustup}
|
||||||
which rustup
|
which rustup
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Rustup not found please install rustup #curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
echo "Rustup not found please install rustup #curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
||||||
fi
|
fi
|
||||||
|
%endif
|
||||||
|
|
||||||
echo ${cargo_version}
|
echo ${cargo_version}
|
||||||
|
|
||||||
|
%if 0%{?using_rustup}
|
||||||
rustup target list --installed | grep x86_64-unknown-linux-gnu
|
rustup target list --installed | grep x86_64-unknown-linux-gnu
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Target x86_64-unknown-linux-gnu not found, please install(#rustup target add x86_64-unknown-linux-gnu). exiting"
|
echo "Target x86_64-unknown-linux-gnu not found, please install(#rustup target add x86_64-unknown-linux-gnu). exiting"
|
||||||
fi
|
fi
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
rustup target list --installed | grep x86_64-unknown-linux-musl
|
rustup target list --installed | grep x86_64-unknown-linux-musl
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Target x86_64-unknown-linux-musl not found, please install(#rustup target add x86_64-unknown-linux-musl). exiting"
|
echo "Target x86_64-unknown-linux-musl not found, please install(#rustup target add x86_64-unknown-linux-musl). exiting"
|
||||||
fi
|
fi
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
|
||||||
cargo build --release --target=x86_64-unknown-linux-gnu --all
|
cargo build --release --target=x86_64-unknown-linux-gnu --all
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
cargo build --release --target=x86_64-unknown-linux-musl --all
|
cargo build --release --target=x86_64-unknown-linux-musl --all
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
@@ -75,19 +97,33 @@ rm -rf %{buildroot}
|
|||||||
|
|
||||||
%files
|
%files
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%{_bindir}/*
|
%{_bindir}/ch-remote
|
||||||
%{_libdir}/cloud-hypervisor
|
%caps(cap_net_admin=ep) %{_bindir}/cloud-hypervisor
|
||||||
|
%{_libdir}/cloud-hypervisor/vhost_user_block
|
||||||
|
%caps(cap_net_admin=ep) %{_libdir}/cloud-hypervisor/vhost_user_net
|
||||||
|
%if 0%{?using_musl_libc}
|
||||||
|
%{_libdir}/cloud-hypervisor/static/ch-remote
|
||||||
|
%caps(cap_net_admim=ep) %{_libdir}/cloud-hypervisor/static/cloud-hypervisor
|
||||||
|
%{_libdir}/cloud-hypervisor/static/vhost_user_block
|
||||||
|
%caps(cap_net_admin=ep) %{_libdir}/cloud-hypervisor/static/vhost_user_net
|
||||||
|
%endif
|
||||||
%license LICENSE-APACHE
|
%license LICENSE-APACHE
|
||||||
%license LICENSE-BSD-3-Clause
|
%license LICENSE-BSD-3-Clause
|
||||||
|
|
||||||
%post
|
|
||||||
setcap cap_net_admin+ep %{_bindir}/cloud-hypervisor
|
|
||||||
setcap cap_net_admin+ep %{_libdir}/cloud-hypervisor/vhost_user_net
|
|
||||||
setcap cap_net_admin+ep %{_libdir}/cloud-hypervisor/static/cloud-hypervisor
|
|
||||||
setcap cap_net_admin+ep %{_libdir}/cloud-hypervisor/static/vhost_user_net
|
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 10 2022 Rob Bradford <robert.bradford@intel.com> 21.1-0
|
||||||
|
- Update to 21.1
|
||||||
|
|
||||||
|
* Thu Jan 20 2022 Rob Bradford <robert.bradford@intel.com> 21.0-0
|
||||||
|
- Update to 21.0
|
||||||
|
|
||||||
|
* Thu Dec 02 2021 Sebastien Boeuf <sebastien.boeuf@intel.com> 20.0-0
|
||||||
|
- Update to 20.0
|
||||||
|
|
||||||
|
* Mon Nov 08 2021 Fabiano Fidêncio <fabiano.fidencio@intel.com> 19.0-0
|
||||||
|
- Update to 19.0
|
||||||
|
|
||||||
* Fri May 28 2021 Muminul Islam <muislam@microsoft.com> 15.0-0
|
* Fri May 28 2021 Muminul Islam <muislam@microsoft.com> 15.0-0
|
||||||
- Update version to 15.0
|
- Update version to 15.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
rm /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/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/meta-data ::
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ checkout_repo() {
|
|||||||
build_custom_linux() {
|
build_custom_linux() {
|
||||||
SRCDIR=$PWD
|
SRCDIR=$PWD
|
||||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
||||||
LINUX_CUSTOM_BRANCH="ch-5.14"
|
LINUX_CUSTOM_BRANCH="ch-5.15.12"
|
||||||
LINUX_CUSTOM_URL="https://github.com/cloud-hypervisor/linux.git"
|
LINUX_CUSTOM_URL="https://github.com/cloud-hypervisor/linux.git"
|
||||||
|
|
||||||
checkout_repo "$LINUX_CUSTOM_DIR" "$LINUX_CUSTOM_URL" "$LINUX_CUSTOM_BRANCH"
|
checkout_repo "$LINUX_CUSTOM_DIR" "$LINUX_CUSTOM_URL" "$LINUX_CUSTOM_BRANCH"
|
||||||
@@ -102,6 +102,25 @@ build_edk2() {
|
|||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_spdk_nvme() {
|
||||||
|
SPDK_DIR="$WORKLOADS_DIR/spdk"
|
||||||
|
SPDK_REPO="https://github.com/spdk/spdk.git"
|
||||||
|
checkout_repo "$SPDK_DIR" "$SPDK_REPO" master "f9c496b8e21a8f499df268818bf8b5d8e2b19f04"
|
||||||
|
|
||||||
|
pushd $SPDK_DIR
|
||||||
|
git submodule update --init
|
||||||
|
apt-get update
|
||||||
|
./scripts/pkgdep.sh
|
||||||
|
./configure --with-vfio-user
|
||||||
|
chmod +x /usr/local/lib/python3.8/dist-packages/ninja/data/bin/ninja
|
||||||
|
make -j `nproc`
|
||||||
|
mkdir /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 -r ./scripts/rpc /usr/local/bin/spdk-nvme
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
update_workloads() {
|
update_workloads() {
|
||||||
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
|
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
|
||||||
|
|
||||||
@@ -203,8 +222,8 @@ update_workloads() {
|
|||||||
if [ ! -f "$VIRTIOFSD_RS" ]; then
|
if [ ! -f "$VIRTIOFSD_RS" ]; then
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
git clone "https://gitlab.com/virtio-fs/virtiofsd-rs.git" $VIRTIOFSD_RS_DIR
|
git clone "https://gitlab.com/virtio-fs/virtiofsd-rs.git" $VIRTIOFSD_RS_DIR
|
||||||
git checkout c847ab63acabed2ed6e6913b9c76bb5099a1d4cb
|
|
||||||
pushd $VIRTIOFSD_RS_DIR
|
pushd $VIRTIOFSD_RS_DIR
|
||||||
|
git checkout 21d20035a582fb0389697b1bd7f8331623a77939
|
||||||
time cargo build --release
|
time cargo build --release
|
||||||
cp target/release/virtiofsd-rs $VIRTIOFSD_RS || exit 1
|
cp target/release/virtiofsd-rs $VIRTIOFSD_RS || exit 1
|
||||||
popd
|
popd
|
||||||
@@ -233,6 +252,9 @@ update_workloads() {
|
|||||||
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
echo "bar" > "$SHARED_DIR/file3" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# checkout and build SPDK NVMe
|
||||||
|
build_spdk_nvme
|
||||||
|
|
||||||
# Check and build EDK2 binary
|
# Check and build EDK2 binary
|
||||||
build_edk2
|
build_edk2
|
||||||
}
|
}
|
||||||
@@ -245,8 +267,8 @@ if [[ "$hypervisor" = "mshv" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
features_build=""
|
# For now these values are deafult for kvm
|
||||||
features_test="--features integration_tests"
|
features=""
|
||||||
|
|
||||||
# lock the workloads folder to avoid parallel updating by different containers
|
# lock the workloads folder to avoid parallel updating by different containers
|
||||||
(
|
(
|
||||||
@@ -273,7 +295,7 @@ fi
|
|||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
# Test without ACPI
|
# Test without ACPI
|
||||||
cargo build --all --release $features_build --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
strip target/$BUILD_TARGET/release/vhost_user_net
|
strip target/$BUILD_TARGET/release/vhost_user_net
|
||||||
strip target/$BUILD_TARGET/release/ch-remote
|
strip target/$BUILD_TARGET/release/ch-remote
|
||||||
@@ -284,17 +306,18 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
|
|||||||
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||||
|
|
||||||
# Setup huge-pages for ovs-dpdk
|
# Both test_vfio and ovs-dpdk rely on hugepages
|
||||||
echo 2048 | sudo tee /proc/sys/vm/nr_hugepages
|
echo 6144 | sudo tee /proc/sys/vm/nr_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`
|
||||||
time cargo test $features_test "tests::parallel::$test_filter"
|
time cargo test $features "parallel::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
# Run some tests in sequence since the result could be affected by other tests
|
# Run some tests in sequence since the result could be affected by other tests
|
||||||
# running in parallel.
|
# running in parallel.
|
||||||
if [ $RES -eq 0 ]; then
|
if [ $RES -eq 0 ]; then
|
||||||
time cargo test $features_test "tests::sequential::$test_filter" -- --test-threads=1
|
time cargo test $features "sequential::$test_filter" -- --test-threads=1
|
||||||
RES=$?
|
RES=$?
|
||||||
else
|
else
|
||||||
exit $RES
|
exit $RES
|
||||||
@@ -302,7 +325,7 @@ fi
|
|||||||
|
|
||||||
# Run all ACPI test cases
|
# Run all ACPI test cases
|
||||||
if [ $RES -eq 0 ]; then
|
if [ $RES -eq 0 ]; then
|
||||||
time cargo test $features_test "tests::aarch64_acpi::$test_filter"
|
time cargo test $features "aarch64_acpi::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
else
|
else
|
||||||
exit $RES
|
exit $RES
|
||||||
@@ -310,7 +333,7 @@ fi
|
|||||||
|
|
||||||
# Run all test cases related to live migration
|
# Run all test cases related to live migration
|
||||||
if [ $RES -eq 0 ]; then
|
if [ $RES -eq 0 ]; then
|
||||||
time cargo test $features_test "tests::live_migration::$test_filter" -- --test-threads=1
|
time cargo test $features "live_migration::$test_filter" -- --test-threads=1
|
||||||
RES=$?
|
RES=$?
|
||||||
else
|
else
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -11,13 +11,11 @@ mkdir -p "$WORKLOADS_DIR"
|
|||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
|
|
||||||
# For now these values are deafult for kvm
|
# For now these values are default for kvm
|
||||||
features_build=""
|
features=""
|
||||||
features_test="--features integration_tests"
|
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
features_build="--no-default-features --features mshv,common"
|
features="--no-default-features --features mshv,common"
|
||||||
features_test="--no-default-features --features mshv,common,integration_tests"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
|
||||||
@@ -55,7 +53,7 @@ LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
|||||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||||
SRCDIR=$PWD
|
SRCDIR=$PWD
|
||||||
pushd $WORKLOADS_DIR
|
pushd $WORKLOADS_DIR
|
||||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.14" $LINUX_CUSTOM_DIR
|
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.15.12" $LINUX_CUSTOM_DIR
|
||||||
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
@@ -79,7 +77,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 --all --release $features_build --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
strip target/$BUILD_TARGET/release/vhost_user_net
|
strip target/$BUILD_TARGET/release/vhost_user_net
|
||||||
strip target/$BUILD_TARGET/release/ch-remote
|
strip target/$BUILD_TARGET/release/ch-remote
|
||||||
@@ -89,7 +87,7 @@ echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
|||||||
sudo chmod a+rwX /dev/hugepages
|
sudo chmod a+rwX /dev/hugepages
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
time cargo test $features_test "tests::live_migration::$test_filter" -- --test-threads=1
|
time cargo test $features "live_migration::$test_filter" -- --test-threads=1
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ if [[ "$hypervisor" = "mshv" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For now these values are deafult for kvm
|
# For now these values are default for kvm
|
||||||
features_build=""
|
features=""
|
||||||
features_test="--features integration_tests"
|
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
@@ -23,12 +22,12 @@ 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 --all --release $features_build --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
time cargo test $features_test "tests::sgx::$test_filter"
|
time cargo test $features "sgx::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ source $HOME/.cargo/env
|
|||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
# For now these values are deafult for kvm
|
# For now these values are default for kvm
|
||||||
features_build=""
|
features=""
|
||||||
features_test="--features integration_tests"
|
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
@@ -17,12 +16,12 @@ 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 --all --release $features_build --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
time cargo test $features_test "tests::vfio::$test_filter" -- --test-threads=1
|
time cargo test $features "vfio::$test_filter" -- --test-threads=1
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
exit $RES
|
exit $RES
|
||||||
|
|||||||
@@ -5,16 +5,23 @@ source $HOME/.cargo/env
|
|||||||
source $(dirname "$0")/test-util.sh
|
source $(dirname "$0")/test-util.sh
|
||||||
|
|
||||||
process_common_args "$@"
|
process_common_args "$@"
|
||||||
# For now these values are deafult for kvm
|
# For now these values are default for kvm
|
||||||
features_build=""
|
features=""
|
||||||
features_test="--features integration_tests"
|
|
||||||
|
|
||||||
if [ "$hypervisor" = "mshv" ] ; then
|
if [ "$hypervisor" = "mshv" ] ; then
|
||||||
features_build="--no-default-features --features mshv,common"
|
features="--no-default-features --features mshv,common"
|
||||||
features_test="--no-default-features --features mshv,common,integration_tests"
|
|
||||||
fi
|
fi
|
||||||
WIN_IMAGE_FILE="/root/workloads/windows-server-2019.raw"
|
WIN_IMAGE_FILE="/root/workloads/windows-server-2019.raw"
|
||||||
OVMF_FW_FILE="/root/workloads/OVMF-4b47d0c6c8.fd"
|
|
||||||
|
WORKLOADS_DIR="/root/workloads"
|
||||||
|
OVMF_FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/edk2/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
|
||||||
|
OVMF_FW="$WORKLOADS_DIR/CLOUDHV.fd"
|
||||||
|
if [ ! -f "$OVMF_FW" ]; then
|
||||||
|
pushd $WORKLOADS_DIR
|
||||||
|
time wget --quiet $OVMF_FW_URL || exit 1
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||||
CFLAGS=""
|
CFLAGS=""
|
||||||
TARGET_CC=""
|
TARGET_CC=""
|
||||||
@@ -24,7 +31,7 @@ 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
|
||||||
if [[ ! -f ${WIN_IMAGE_FILE} || ! -f ${OVMF_FW_FILE} ]]; then
|
if [[ ! -f ${WIN_IMAGE_FILE} || ! -f ${OVMF_FW} ]]; then
|
||||||
echo "Windows image/firmware not present in the host"
|
echo "Windows image/firmware not present in the host"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -37,14 +44,14 @@ 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 --all --release $features_build --target $BUILD_TARGET
|
cargo build --all --release $features --target $BUILD_TARGET
|
||||||
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
strip target/$BUILD_TARGET/release/cloud-hypervisor
|
||||||
|
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
|
||||||
# Only run with 1 thread to avoid tests interfering with one another because
|
# Only run with 1 thread to avoid tests interfering with one another because
|
||||||
# Windows has a static IP configured
|
# Windows has a static IP configured
|
||||||
time cargo test $features_test "tests::windows::$test_filter"
|
time cargo test $features "windows::$test_filter"
|
||||||
RES=$?
|
RES=$?
|
||||||
|
|
||||||
dmsetup remove_all -f
|
dmsetup remove_all -f
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user