mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
20 Commits
v32.1
...
stable/v30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93d7e01b41 | ||
|
|
4fe593e12d | ||
|
|
4203a61947 | ||
|
|
e397e739bf | ||
|
|
2724edd1e5 | ||
|
|
269844da73 | ||
|
|
a299a10874 | ||
|
|
015941e294 | ||
|
|
ca6fe2a98e | ||
|
|
f4090b0196 | ||
|
|
3432c0ce5e | ||
|
|
ec70af1606 | ||
|
|
bb0d82c365 | ||
|
|
2d98a16d05 | ||
|
|
cd1a645421 | ||
|
|
4485210de5 | ||
|
|
0aa858c266 | ||
|
|
499e8433c3 | ||
|
|
ff27b00f5a | ||
|
|
d09af361bc |
20
.github/workflows/docker-image.yaml
vendored
20
.github/workflows/docker-image.yaml
vendored
@@ -7,10 +7,6 @@ on:
|
||||
pull_request:
|
||||
paths: resources/Dockerfile
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,19 +20,19 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v2
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# list of Docker images to use as base name for tags
|
||||
images: cloudhypervisor/dev
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value={{date 'YYYYMMDD'}}-0
|
||||
|
||||
10
.github/workflows/release.yaml
vendored
10
.github/workflows/release.yaml
vendored
@@ -16,29 +16,29 @@ jobs:
|
||||
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.67.1"
|
||||
toolchain: "1.62"
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.67.1"
|
||||
toolchain: "1.62"
|
||||
target: x86_64-unknown-linux-musl
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
toolchain: "1.67.1"
|
||||
toolchain: "1.62"
|
||||
command: build
|
||||
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-gnu
|
||||
- name: Static Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
toolchain: "1.67.1"
|
||||
toolchain: "1.62"
|
||||
command: build
|
||||
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-musl
|
||||
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.67.1"
|
||||
toolchain: "1.62"
|
||||
target: aarch64-unknown-linux-musl
|
||||
override: true
|
||||
- name: Create Release
|
||||
|
||||
280
Cargo.lock
generated
280
Cargo.lock
generated
@@ -5,9 +5,9 @@ version = 3
|
||||
[[package]]
|
||||
name = "acpi_tables"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#98dcb0309d362dd83f6ffcac4f66914a2fbd5a73"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#12bb6d7b252831527e630f8b3ef48877dbb11924"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -36,9 +36,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.70"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||
|
||||
[[package]]
|
||||
name = "api_client"
|
||||
@@ -179,7 +179,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "32.1.0"
|
||||
version = "30.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
@@ -224,9 +224,9 @@ checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
|
||||
checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
@@ -234,9 +234,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.14.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
|
||||
checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
@@ -248,9 +248,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.14.4"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
|
||||
checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
@@ -297,22 +297,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.0"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.0"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
|
||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"windows-sys 0.45.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -340,13 +340,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -382,9 +382,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "gdbstub"
|
||||
version = "0.6.4"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba4fddc6f9d12cbef29e395d9a6b48c128f513c8a2ded7048c97ed5c484e53e7"
|
||||
checksum = "32c95766e0414f8bfc1d07055574c621b67739466d6ba516c4fef8e99d30d2e6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -487,20 +487,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.5.13"
|
||||
version = "0.5.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd1e1a01cfb924fd8c5c43b6827965db394f5a3a16c599ce03452266e1cf984c"
|
||||
checksum = "41c85eff7f7c8d3ab8c7ec87313c0c194bbaf4371bb7d40f80293ba01bce8264"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
@@ -517,21 +516,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.7"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
||||
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "kvm-bindings"
|
||||
@@ -602,9 +601,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.2"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@@ -668,7 +667,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "mshv-bindings"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#c1230f282c2836ba89ee112146bf638343424de8"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#0b2af251285385f8e39c2cd0fe8ffacab534932f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"serde",
|
||||
@@ -680,7 +679,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "mshv-ioctls"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#c1230f282c2836ba89ee112146bf638343424de8"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#0b2af251285385f8e39c2cd0fe8ffacab534932f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mshv-bindings",
|
||||
@@ -760,9 +759,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.83"
|
||||
version = "0.9.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b"
|
||||
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
@@ -826,9 +825,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.12"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
||||
|
||||
[[package]]
|
||||
name = "pci"
|
||||
@@ -965,9 +964,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.52"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1034,9 +1033,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "remain"
|
||||
@@ -1051,9 +1050,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
@@ -1072,9 +1071,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.3"
|
||||
version = "0.36.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2"
|
||||
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@@ -1086,9 +1085,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@@ -1107,24 +1106,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.156"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.156"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1133,9 +1132,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.96"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1144,9 +1143,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "2.3.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331bb8c3bf9b92457ab7abecf07078c13f7d270ba490103e84e8b014490cd0b0"
|
||||
checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_with_macros",
|
||||
@@ -1154,9 +1153,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "2.3.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "859011bddcc11f289f07f467cc1fe01c7a941daa4d8f6c40d4d1c92eb6d9319c"
|
||||
checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
@@ -1170,9 +1169,9 @@ version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.15"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
|
||||
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
@@ -1258,18 +1257,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.39"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.39"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1329,9 +1328,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.1.10"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca4b7062e7e6d685901e815c35f9671e059de97c1c0905eeff8592f3fff442f"
|
||||
checksum = "d6e2495726cf917e7ba7ec8bf0f0fceab543dd38d0a4195ed6bef331e38a290f"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
@@ -1357,7 +1356,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vfio-bindings"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#ea8f710464a24690ce109e6b7dfaa623dc518304"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
|
||||
dependencies = [
|
||||
"vmm-sys-util",
|
||||
]
|
||||
@@ -1365,7 +1364,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vfio-ioctls"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#ea8f710464a24690ce109e6b7dfaa623dc518304"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"kvm-bindings",
|
||||
@@ -1383,7 +1382,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vfio_user"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#e75c9415d973769c5fd1d07716eb92d6e5be7c48"
|
||||
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#afbbd5722885e961ce12baea12efe01d52ce14b0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
@@ -1524,9 +1523,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "virtio-queue"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ba81e2bcc21c0d2fc5e6683e79367e26ad219197423a498df801d79d5ba77bd"
|
||||
checksum = "19e927d93d54c365034fd7f31a5f458a1f540de4a37c52e892670dad9692173c"
|
||||
dependencies = [
|
||||
"log",
|
||||
"virtio-bindings 0.1.0",
|
||||
@@ -1559,7 +1558,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vm-fdt"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#ad21ede0ddb4cc97448eeb64c1dfc27803b9ec08"
|
||||
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927d19b50c85fcd5ce904a8c"
|
||||
|
||||
[[package]]
|
||||
name = "vm-memory"
|
||||
@@ -1640,7 +1639,6 @@ dependencies = [
|
||||
"vm-migration",
|
||||
"vm-virtio",
|
||||
"vmm-sys-util",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1707,13 +1705,13 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1722,131 +1720,65 @@ version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cloud-hypervisor"
|
||||
version = "32.1.0"
|
||||
version = "30.1.0"
|
||||
authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
default-run = "cloud-hypervisor"
|
||||
@@ -29,7 +29,7 @@ strip = false
|
||||
debug = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
api_client = { path = "api_client" }
|
||||
argh = "0.1.9"
|
||||
dhat = { version = "0.3.2", optional = true }
|
||||
@@ -40,9 +40,9 @@ libc = "0.2.139"
|
||||
log = { version = "0.4.17", features = ["std"] }
|
||||
option_parser = { path = "option_parser" }
|
||||
seccompiler = "0.3.0"
|
||||
serde_json = "1.0.96"
|
||||
signal-hook = "0.3.15"
|
||||
thiserror = "1.0.39"
|
||||
serde_json = "1.0.93"
|
||||
signal-hook = "0.3.14"
|
||||
thiserror = "1.0.38"
|
||||
tpm = { path = "tpm"}
|
||||
tracer = { path = "tracer" }
|
||||
vmm = { path = "vmm" }
|
||||
@@ -56,10 +56,10 @@ kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
|
||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
|
||||
|
||||
[dev-dependencies]
|
||||
dirs = "5.0.0"
|
||||
dirs = "4.0.0"
|
||||
net_util = { path = "net_util" }
|
||||
once_cell = "1.17.1"
|
||||
serde_json = "1.0.96"
|
||||
serde_json = "1.0.93"
|
||||
test_infra = { path = "test_infra" }
|
||||
wait-timeout = "0.2.0"
|
||||
|
||||
|
||||
92
Jenkinsfile
vendored
92
Jenkinsfile
vendored
@@ -192,52 +192,52 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
// stage('Worker build - Windows guest') {
|
||||
// agent { node { label 'jammy' } }
|
||||
// when {
|
||||
// beforeAgent true
|
||||
// expression {
|
||||
// return runWorkers
|
||||
// }
|
||||
// }
|
||||
// environment {
|
||||
// AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
|
||||
// }
|
||||
// stages {
|
||||
// stage('Checkout') {
|
||||
// steps {
|
||||
// checkout scm
|
||||
// }
|
||||
// }
|
||||
// stage('Install azure-cli') {
|
||||
// steps {
|
||||
// installAzureCli('jammy', 'amd64')
|
||||
// }
|
||||
// }
|
||||
// stage('Download assets') {
|
||||
// steps {
|
||||
// sh "mkdir ${env.HOME}/workloads"
|
||||
// sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2022-amd64-2.raw" --name windows-server-2022-amd64-2.raw --connection-string "$AZURE_CONNECTION_STRING"'
|
||||
// }
|
||||
// }
|
||||
// stage('Run Windows guest integration tests') {
|
||||
// options {
|
||||
// timeout(time: 1, unit: 'HOURS')
|
||||
// }
|
||||
// steps {
|
||||
// sh 'scripts/dev_cli.sh tests --integration-windows'
|
||||
// }
|
||||
// }
|
||||
// stage('Run Windows guest integration tests for musl') {
|
||||
// options {
|
||||
// timeout(time: 1, unit: 'HOURS')
|
||||
// }
|
||||
// steps {
|
||||
// sh 'scripts/dev_cli.sh tests --integration-windows --libc musl'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
stage('Worker build - Windows guest') {
|
||||
agent { node { label 'jammy' } }
|
||||
when {
|
||||
beforeAgent true
|
||||
expression {
|
||||
return runWorkers
|
||||
}
|
||||
}
|
||||
environment {
|
||||
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
|
||||
}
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
stage('Install azure-cli') {
|
||||
steps {
|
||||
installAzureCli('jammy', 'amd64')
|
||||
}
|
||||
}
|
||||
stage('Download assets') {
|
||||
steps {
|
||||
sh "mkdir ${env.HOME}/workloads"
|
||||
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2022-amd64-2.raw" --name windows-server-2022-amd64-2.raw --connection-string "$AZURE_CONNECTION_STRING"'
|
||||
}
|
||||
}
|
||||
stage('Run Windows guest integration tests') {
|
||||
options {
|
||||
timeout(time: 1, unit: 'HOURS')
|
||||
}
|
||||
steps {
|
||||
sh 'scripts/dev_cli.sh tests --integration-windows'
|
||||
}
|
||||
}
|
||||
stage('Run Windows guest integration tests for musl') {
|
||||
options {
|
||||
timeout(time: 1, unit: 'HOURS')
|
||||
}
|
||||
steps {
|
||||
sh 'scripts/dev_cli.sh tests --integration-windows --libc musl'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Worker build - Metrics') {
|
||||
agent { node { label 'jammy-metrics' } }
|
||||
when {
|
||||
|
||||
10
README.md
10
README.md
@@ -113,7 +113,7 @@ Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware) or an
|
||||
edk2 UEFI firmware called `CLOUDHV` / `CLOUDHV_EFI`.)
|
||||
|
||||
Binary builds of the firmware files are available for the latest release of
|
||||
[Rust Hypervisor
|
||||
[Rust Hyperivor
|
||||
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/latest)
|
||||
and [our edk2
|
||||
repository](https://github.com/cloud-hypervisor/edk2/releases/latest)
|
||||
@@ -124,7 +124,7 @@ may be required.
|
||||
### Firmware Booting
|
||||
|
||||
Cloud Hypervisor supports booting disk images containing all needed components
|
||||
to run cloud workloads, a.k.a. cloud images.
|
||||
to run cloud workloads, a.k.a. cloud images.
|
||||
|
||||
The following sample commands will download an Ubuntu Cloud image, converting
|
||||
it into a format that Cloud Hypervisor can use and a firmware to boot the image
|
||||
@@ -178,7 +178,7 @@ To build the kernel:
|
||||
|
||||
```shell
|
||||
# Clone the Cloud Hypervisor Linux branch
|
||||
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.2 linux-cloud-hypervisor
|
||||
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.1.6 linux-cloud-hypervisor
|
||||
$ pushd linux-cloud-hypervisor
|
||||
# Use the x86-64 cloud-hypervisor kernel config to build your kernel for x86-64
|
||||
$ wget https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/main/resources/linux-config-x86_64
|
||||
@@ -372,8 +372,8 @@ are all equal and welcome means of contribution. See the
|
||||
|
||||
## Slack
|
||||
|
||||
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI),
|
||||
[join us on Slack](https://cloud-hypervisor.slack.com/), and [participate in our community activities](https://cloud-hypervisor.slack.com/archives/C04R5DUQVBN).
|
||||
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI)
|
||||
and [join us on Slack](https://cloud-hypervisor.slack.com/).
|
||||
|
||||
## Mailing list
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@ default = []
|
||||
tdx = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
byteorder = "1.4.3"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
libc = "0.2.139"
|
||||
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
|
||||
log = "0.4.17"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.39"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.38"
|
||||
uuid = "1.3.0"
|
||||
versionize = "0.1.10"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
|
||||
@@ -260,86 +260,32 @@ fn create_memory_node(
|
||||
fdt.end_node(memory_node)?;
|
||||
}
|
||||
} else {
|
||||
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
|
||||
let ram_regions = {
|
||||
let mut ram_regions = Vec::new();
|
||||
let mut current_start = guest_mem
|
||||
.iter()
|
||||
.next()
|
||||
.map(GuestMemoryRegion::start_addr)
|
||||
.expect("GuestMemory must have one memory region at least")
|
||||
.raw_value();
|
||||
let mut current_end = current_start;
|
||||
|
||||
for (start, size) in guest_mem
|
||||
.iter()
|
||||
.map(|m| (m.start_addr().raw_value(), m.len()))
|
||||
{
|
||||
if current_end == start {
|
||||
// This zone is continuous with the previous one.
|
||||
current_end += size;
|
||||
} else {
|
||||
ram_regions.push((current_start, current_end));
|
||||
|
||||
current_start = start;
|
||||
current_end = start + size;
|
||||
}
|
||||
}
|
||||
|
||||
ram_regions.push((current_start, current_end));
|
||||
|
||||
ram_regions
|
||||
};
|
||||
|
||||
if ram_regions.len() > 2 {
|
||||
panic!(
|
||||
"There should be up to two non-continuous regions, devidided by the
|
||||
gap at the end of 32bit address space."
|
||||
);
|
||||
}
|
||||
|
||||
// Create the memory node for memory region before the gap
|
||||
{
|
||||
let (first_region_start, first_region_end) = ram_regions
|
||||
.first()
|
||||
.expect("There should be at last one memory region");
|
||||
let ram_start = super::layout::RAM_START.raw_value();
|
||||
let mem_32bit_reserved_start = super::layout::MEM_32BIT_RESERVED_START.raw_value();
|
||||
|
||||
if !((first_region_start <= &ram_start)
|
||||
&& (first_region_end > &ram_start)
|
||||
&& (first_region_end <= &mem_32bit_reserved_start))
|
||||
{
|
||||
panic!(
|
||||
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
|
||||
ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
|
||||
first_region_start, first_region_end, ram_start, mem_32bit_reserved_start
|
||||
);
|
||||
}
|
||||
|
||||
let mem_size = first_region_end - ram_start;
|
||||
let mem_reg_prop = [ram_start, mem_size];
|
||||
let memory_node_name = format!("memory@{:x}", ram_start);
|
||||
let last_addr = guest_mem.last_addr().raw_value();
|
||||
if last_addr < super::layout::MEM_32BIT_RESERVED_START.raw_value() {
|
||||
// Case 1: all RAM is under the hole
|
||||
let mem_size = last_addr - super::layout::RAM_START.raw_value() + 1;
|
||||
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
|
||||
let memory_node = fdt.begin_node("memory")?;
|
||||
fdt.property_string("device_type", "memory")?;
|
||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||
fdt.end_node(memory_node)?;
|
||||
} else {
|
||||
// Case 2: RAM is split by the hole
|
||||
// Region 1: RAM before the hole
|
||||
let mem_size = super::layout::MEM_32BIT_RESERVED_START.raw_value()
|
||||
- super::layout::RAM_START.raw_value();
|
||||
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
|
||||
let memory_node_name = format!("memory@{:x}", super::layout::RAM_START.raw_value());
|
||||
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||
fdt.property_string("device_type", "memory")?;
|
||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||
fdt.end_node(memory_node)?;
|
||||
}
|
||||
|
||||
// Create the memory map entry for memory region after the gap if any
|
||||
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
|
||||
let ram_64bit_start = super::layout::RAM_64BIT_START.raw_value();
|
||||
|
||||
if second_region_start != &ram_64bit_start {
|
||||
panic!(
|
||||
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
|
||||
second_region_start, ram_64bit_start
|
||||
);
|
||||
}
|
||||
|
||||
let mem_size = second_region_end - ram_64bit_start;
|
||||
let mem_reg_prop = [ram_64bit_start, mem_size];
|
||||
let memory_node_name = format!("memory@{:x}", ram_64bit_start);
|
||||
// Region 2: RAM after the hole
|
||||
let mem_size = last_addr - super::layout::RAM_64BIT_START.raw_value() + 1;
|
||||
let mem_reg_prop = [super::layout::RAM_64BIT_START.raw_value(), mem_size];
|
||||
let memory_node_name =
|
||||
format!("memory@{:x}", super::layout::RAM_64BIT_START.raw_value());
|
||||
let memory_node = fdt.begin_node(&memory_node_name)?;
|
||||
fdt.property_string("device_type", "memory")?;
|
||||
fdt.property_array_u64("reg", &mem_reg_prop)?;
|
||||
|
||||
@@ -19,9 +19,7 @@ use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
|
||||
|
||||
pub const _NSIG: i32 = 65;
|
||||
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic, GuestUsize};
|
||||
|
||||
/// Errors thrown while configuring aarch64 system.
|
||||
#[derive(Debug)]
|
||||
@@ -83,8 +81,8 @@ pub fn configure_vcpu(
|
||||
Ok(mpidr)
|
||||
}
|
||||
|
||||
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
vec![
|
||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
let mut regions = vec![
|
||||
// 0 MiB ~ 256 MiB: UEFI, GIC and legacy devices
|
||||
(
|
||||
GuestAddress(0),
|
||||
@@ -103,21 +101,39 @@ pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
layout::PCI_MMCONFIG_SIZE as usize,
|
||||
RegionType::Reserved,
|
||||
),
|
||||
// 1GiB ~ 4032 MiB: RAM before the gap
|
||||
(
|
||||
];
|
||||
|
||||
let ram_32bit_space_size =
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START);
|
||||
|
||||
// RAM space
|
||||
// Case1: guest memory fits before the gap
|
||||
if size <= ram_32bit_space_size {
|
||||
regions.push((layout::RAM_START, size as usize, RegionType::Ram));
|
||||
// Case2: guest memory extends beyond the gap
|
||||
} else {
|
||||
// Push memory before the gap
|
||||
regions.push((
|
||||
layout::RAM_START,
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize,
|
||||
ram_32bit_space_size as usize,
|
||||
RegionType::Ram,
|
||||
),
|
||||
// 4GiB ~ inf: RAM after the gap
|
||||
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
|
||||
// Add the 32-bit reserved memory hole as a reserved region
|
||||
(
|
||||
layout::MEM_32BIT_RESERVED_START,
|
||||
layout::MEM_32BIT_RESERVED_SIZE as usize,
|
||||
RegionType::Reserved,
|
||||
),
|
||||
]
|
||||
));
|
||||
// Other memory is placed after 4GiB
|
||||
regions.push((
|
||||
layout::RAM_64BIT_START,
|
||||
(size - ram_32bit_space_size) as usize,
|
||||
RegionType::Ram,
|
||||
));
|
||||
}
|
||||
|
||||
// Add the 32-bit reserved memory hole as a reserved region
|
||||
regions.push((
|
||||
layout::MEM_32BIT_RESERVED_START,
|
||||
layout::MEM_32BIT_RESERVED_SIZE as usize,
|
||||
RegionType::Reserved,
|
||||
));
|
||||
|
||||
regions
|
||||
}
|
||||
|
||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||
@@ -199,12 +215,26 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_arch_memory_regions_dram() {
|
||||
let regions = arch_memory_regions();
|
||||
fn test_arch_memory_regions_dram_2gb() {
|
||||
let regions = arch_memory_regions((1usize << 31) as u64); //2GB
|
||||
assert_eq!(5, regions.len());
|
||||
assert_eq!(layout::RAM_START, regions[3].0);
|
||||
assert_eq!((1usize << 31), regions[3].1);
|
||||
assert_eq!(RegionType::Ram, regions[3].2);
|
||||
assert_eq!(RegionType::Reserved, regions[4].2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arch_memory_regions_dram_4gb() {
|
||||
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
|
||||
let ram_32bit_space_size =
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize;
|
||||
assert_eq!(6, regions.len());
|
||||
assert_eq!(layout::RAM_START, regions[3].0);
|
||||
assert_eq!(ram_32bit_space_size, regions[3].1);
|
||||
assert_eq!(RegionType::Ram, regions[3].2);
|
||||
assert_eq!(RegionType::Reserved, regions[5].2);
|
||||
assert_eq!(RegionType::Ram, regions[4].2);
|
||||
assert_eq!(((1usize << 32) - ram_32bit_space_size), regions[4].1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// AArch64 system register encoding:
|
||||
// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
|
||||
//
|
||||
// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
|
||||
// +----------+---+-----+-----+-----+-----+-----+----+
|
||||
// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
|
||||
// +----------+---+-----+-----+-----+-----+-----+----+
|
||||
//
|
||||
// Notes:
|
||||
// - L and Rt are reserved as implementation defined fields, ignored.
|
||||
|
||||
///
|
||||
/// AArch64 system register encoding:
|
||||
/// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
|
||||
///
|
||||
/// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
|
||||
/// +----------+---+-----+-----+-----+-----+-----+----+
|
||||
/// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
|
||||
/// +----------+---+-----+-----+-----+-----+-----+----+
|
||||
///
|
||||
/// Notes:
|
||||
/// - L and Rt are reserved as implementation defined fields, ignored.
|
||||
///
|
||||
const SYSREG_HEAD: u32 = 0b1101010100u32 << 22;
|
||||
const SYSREG_OP0_SHIFT: u32 = 19;
|
||||
const SYSREG_OP0_MASK: u32 = 0b11u32 << 19;
|
||||
|
||||
@@ -82,7 +82,7 @@ pub mod aarch64;
|
||||
pub use aarch64::{
|
||||
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
|
||||
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||
layout::IRQ_BASE, uefi, EntryPoint, _NSIG,
|
||||
layout::IRQ_BASE, uefi, EntryPoint,
|
||||
};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -92,7 +92,7 @@ pub mod x86_64;
|
||||
pub use x86_64::{
|
||||
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
|
||||
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, _NSIG,
|
||||
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint,
|
||||
};
|
||||
|
||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||
|
||||
@@ -53,8 +53,6 @@ const KVM_FEATURE_ASYNC_PF_VMEXIT_BIT: u8 = 10;
|
||||
#[cfg(feature = "tdx")]
|
||||
const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
|
||||
|
||||
pub const _NSIG: i32 = 65;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Specifies the entry point address where the guest must start
|
||||
/// executing code, as well as which of the supported boot protocols
|
||||
@@ -210,6 +208,7 @@ impl From<Error> for super::Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum CpuidReg {
|
||||
EAX,
|
||||
@@ -775,13 +774,6 @@ pub fn configure_vcpu(
|
||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
|
||||
|
||||
// Set ApicId in cpuid for each vcpu
|
||||
// SAFETY: get host cpuid when eax=1
|
||||
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx;
|
||||
cpu_ebx &= 0xffffff;
|
||||
cpu_ebx |= (id as u32) << 24;
|
||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
|
||||
|
||||
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation
|
||||
if !kvm_hyperv {
|
||||
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
|
||||
@@ -834,29 +826,47 @@ pub fn configure_vcpu(
|
||||
/// These should be used to configure the GuestMemory structure for the platform.
|
||||
/// For x86_64 all addresses are valid from the start of the kernel except a
|
||||
/// carve out at the end of 32bit address space.
|
||||
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
vec![
|
||||
// 0 GiB ~ 3GiB: memory before the gap
|
||||
(
|
||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
let reserved_memory_gap_start = layout::MEM_32BIT_RESERVED_START
|
||||
.checked_add(layout::MEM_32BIT_DEVICES_SIZE)
|
||||
.expect("32-bit reserved region is too large");
|
||||
|
||||
let requested_memory_size = GuestAddress(size);
|
||||
let mut regions = Vec::new();
|
||||
|
||||
// case1: guest memory fits before the gap
|
||||
if size <= layout::MEM_32BIT_RESERVED_START.raw_value() {
|
||||
regions.push((GuestAddress(0), size as usize, RegionType::Ram));
|
||||
// case2: guest memory extends beyond the gap
|
||||
} else {
|
||||
// push memory before the gap
|
||||
regions.push((
|
||||
GuestAddress(0),
|
||||
layout::MEM_32BIT_RESERVED_START.raw_value() as usize,
|
||||
RegionType::Ram,
|
||||
),
|
||||
// 4 GiB ~ inf: memory after the gap
|
||||
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
|
||||
// 3 GiB ~ 3712 MiB: 32-bit device memory hole
|
||||
(
|
||||
layout::MEM_32BIT_RESERVED_START,
|
||||
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
||||
RegionType::SubRegion,
|
||||
),
|
||||
// 3712 MiB ~ 3968 MiB: 32-bit reserved memory hole
|
||||
(
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_add(layout::MEM_32BIT_DEVICES_SIZE),
|
||||
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_SIZE) as usize,
|
||||
RegionType::Reserved,
|
||||
),
|
||||
]
|
||||
));
|
||||
regions.push((
|
||||
layout::RAM_64BIT_START,
|
||||
requested_memory_size.unchecked_offset_from(layout::MEM_32BIT_RESERVED_START) as usize,
|
||||
RegionType::Ram,
|
||||
));
|
||||
}
|
||||
|
||||
// Add the 32-bit device memory hole as a sub region.
|
||||
regions.push((
|
||||
layout::MEM_32BIT_RESERVED_START,
|
||||
layout::MEM_32BIT_DEVICES_SIZE as usize,
|
||||
RegionType::SubRegion,
|
||||
));
|
||||
|
||||
// Add the 32-bit reserved memory hole as a sub region.
|
||||
regions.push((
|
||||
reserved_memory_gap_start,
|
||||
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_SIZE) as usize,
|
||||
RegionType::Reserved,
|
||||
));
|
||||
|
||||
regions
|
||||
}
|
||||
|
||||
/// Configures the system and should be called once per vm before starting vcpu threads.
|
||||
@@ -954,102 +964,30 @@ fn configure_pvh(
|
||||
// Create the memory map entries.
|
||||
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
|
||||
|
||||
// Merge continuous memory regions into one region.
|
||||
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
|
||||
let ram_regions = {
|
||||
let mut ram_regions = Vec::new();
|
||||
let mut current_start = guest_mem
|
||||
.iter()
|
||||
.next()
|
||||
.map(GuestMemoryRegion::start_addr)
|
||||
.expect("GuestMemory must have one memory region at least")
|
||||
.raw_value();
|
||||
let mut current_end = current_start;
|
||||
|
||||
for (start, size) in guest_mem
|
||||
.iter()
|
||||
.map(|m| (m.start_addr().raw_value(), m.len()))
|
||||
{
|
||||
if current_end == start {
|
||||
// This zone is continuous with the previous one.
|
||||
current_end += size;
|
||||
} else {
|
||||
ram_regions.push((current_start, current_end));
|
||||
|
||||
current_start = start;
|
||||
current_end = start + size;
|
||||
}
|
||||
}
|
||||
|
||||
ram_regions.push((current_start, current_end));
|
||||
|
||||
ram_regions
|
||||
};
|
||||
|
||||
if ram_regions.len() > 2 {
|
||||
error!(
|
||||
"There should be up to two non-continuous regions, devidided by the
|
||||
gap at the end of 32bit address space (e.g. between 3G and 4G)."
|
||||
);
|
||||
return Err(super::Error::MemmapTableSetup);
|
||||
}
|
||||
|
||||
// Create the memory map entry for memory region before the gap
|
||||
{
|
||||
let (first_region_start, first_region_end) =
|
||||
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
|
||||
let high_ram_start = layout::HIGH_RAM_START.raw_value();
|
||||
let mem_32bit_reserved_start = layout::MEM_32BIT_RESERVED_START.raw_value();
|
||||
|
||||
if !((first_region_start <= &high_ram_start)
|
||||
&& (first_region_end > &high_ram_start)
|
||||
&& (first_region_end <= &mem_32bit_reserved_start))
|
||||
{
|
||||
error!(
|
||||
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
|
||||
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
|
||||
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
|
||||
);
|
||||
|
||||
return Err(super::Error::MemmapTableSetup);
|
||||
}
|
||||
|
||||
info!(
|
||||
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x})",
|
||||
high_ram_start, first_region_end
|
||||
);
|
||||
let mem_end = guest_mem.last_addr();
|
||||
|
||||
if mem_end < layout::MEM_32BIT_RESERVED_START {
|
||||
add_memmap_entry(
|
||||
&mut memmap,
|
||||
high_ram_start,
|
||||
first_region_end - high_ram_start,
|
||||
layout::HIGH_RAM_START.raw_value(),
|
||||
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
|
||||
E820_RAM,
|
||||
);
|
||||
}
|
||||
|
||||
// Create the memory map entry for memory region after the gap if any
|
||||
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
|
||||
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
|
||||
|
||||
if second_region_start != &ram_64bit_start {
|
||||
error!(
|
||||
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
|
||||
second_region_start, ram_64bit_start
|
||||
);
|
||||
|
||||
return Err(super::Error::MemmapTableSetup);
|
||||
}
|
||||
|
||||
info!(
|
||||
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x})",
|
||||
ram_64bit_start, second_region_end
|
||||
);
|
||||
} else {
|
||||
add_memmap_entry(
|
||||
&mut memmap,
|
||||
ram_64bit_start,
|
||||
second_region_end - ram_64bit_start,
|
||||
layout::HIGH_RAM_START.raw_value(),
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
|
||||
E820_RAM,
|
||||
);
|
||||
if mem_end > layout::RAM_64BIT_START {
|
||||
add_memmap_entry(
|
||||
&mut memmap,
|
||||
layout::RAM_64BIT_START.raw_value(),
|
||||
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
|
||||
E820_RAM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
add_memmap_entry(
|
||||
@@ -1285,8 +1223,16 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn regions_base_addr() {
|
||||
let regions = arch_memory_regions();
|
||||
fn regions_lt_4gb() {
|
||||
let regions = arch_memory_regions(1 << 29);
|
||||
assert_eq!(3, regions.len());
|
||||
assert_eq!(GuestAddress(0), regions[0].0);
|
||||
assert_eq!(1usize << 29, regions[0].1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regions_gt_4gb() {
|
||||
let regions = arch_memory_regions((1 << 32) + 0x8000);
|
||||
assert_eq!(4, regions.len());
|
||||
assert_eq!(GuestAddress(0), regions[0].0);
|
||||
assert_eq!(GuestAddress(1 << 32), regions[1].0);
|
||||
@@ -1310,10 +1256,11 @@ mod tests {
|
||||
assert!(config_err.is_err());
|
||||
|
||||
// Now assigning some memory that falls before the 32bit memory hole.
|
||||
let arch_mem_regions = arch_memory_regions();
|
||||
let mem_size = 128 << 20;
|
||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||
.iter()
|
||||
.filter(|r| r.2 == RegionType::Ram && r.1 != usize::MAX)
|
||||
.filter(|r| r.2 == RegionType::Ram)
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||
@@ -1331,18 +1278,48 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Now assigning some memory that falls after the 32bit memory hole.
|
||||
let arch_mem_regions = arch_memory_regions();
|
||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
||||
let mem_size = 3328 << 20;
|
||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||
.iter()
|
||||
.filter(|r| r.2 == RegionType::Ram)
|
||||
.map(|r| {
|
||||
if r.1 == usize::MAX {
|
||||
(r.0, 128 << 20)
|
||||
} else {
|
||||
(r.0, r.1)
|
||||
}
|
||||
})
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
&None,
|
||||
no_vcpus,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
&None,
|
||||
no_vcpus,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Now assigning some memory that falls after the 32bit memory hole.
|
||||
let mem_size = 3330 << 20;
|
||||
let arch_mem_regions = arch_memory_regions(mem_size);
|
||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||
.iter()
|
||||
.filter(|r| r.2 == RegionType::Ram)
|
||||
.map(|r| (r.0, r.1))
|
||||
.collect();
|
||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||
configure_system(
|
||||
|
||||
@@ -8,17 +8,17 @@ edition = "2021"
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
io-uring = "0.5.13"
|
||||
io-uring = "0.5.12"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
qcow = { path = "../qcow" }
|
||||
smallvec = "1.10.0"
|
||||
thiserror = "1.0.39"
|
||||
versionize = "0.1.10"
|
||||
thiserror = "1.0.38"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vhdx = { path = "../vhdx" }
|
||||
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.11.0"
|
||||
|
||||
4
build.rs
4
build.rs
@@ -17,8 +17,8 @@ fn main() {
|
||||
}
|
||||
|
||||
// This println!() has a special behavior, as it will set the environment
|
||||
// variable BUILD_VERSION, so that it can be reused from the binary.
|
||||
// variable BUILT_VERSION, so that it can be reused from the binary.
|
||||
// Particularly, this is used from src/main.rs to display the exact
|
||||
// version.
|
||||
println!("cargo:rustc-env=BUILD_VERSION={version}");
|
||||
println!("cargo:rustc-env=BUILT_VERSION={version}");
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
arch = { path = "../arch" }
|
||||
bitflags = "1.3.2"
|
||||
byteorder = "1.4.3"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
thiserror = "1.0.39"
|
||||
thiserror = "1.0.38"
|
||||
tpm = { path = "../tpm" }
|
||||
versionize = "0.1.10"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = "0.10.0"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
|
||||
use super::AcpiNotificationFlags;
|
||||
use acpi_tables::{aml, Aml, AmlSink};
|
||||
use acpi_tables::{aml, aml::Aml};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::Instant;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
@@ -103,11 +103,11 @@ impl BusDevice for AcpiGedDevice {
|
||||
}
|
||||
|
||||
impl Aml for AcpiGedDevice {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
aml::Device::new(
|
||||
"_SB_.GEC_".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
||||
&aml::Name::new("_UID".into(), &"Generic Event Controller"),
|
||||
&aml::Name::new(
|
||||
"_CRS".into(),
|
||||
@@ -121,13 +121,12 @@ impl Aml for AcpiGedDevice {
|
||||
&aml::OpRegion::new(
|
||||
"GDST".into(),
|
||||
aml::OpRegionSpace::SystemMemory,
|
||||
&(self.address.0 as usize),
|
||||
&GED_DEVICE_ACPI_SIZE,
|
||||
self.address.0 as usize,
|
||||
GED_DEVICE_ACPI_SIZE,
|
||||
),
|
||||
&aml::Field::new(
|
||||
"GDST".into(),
|
||||
aml::FieldAccessType::Byte,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::WriteAsZeroes,
|
||||
vec![aml::FieldEntry::Named(*b"GDAT", 8)],
|
||||
),
|
||||
@@ -164,7 +163,7 @@ impl Aml for AcpiGedDevice {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
aml::Device::new(
|
||||
"_SB_.GED_".into(),
|
||||
vec![
|
||||
@@ -188,7 +187,7 @@ impl Aml for AcpiGedDevice {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
65
docs/api.md
65
docs/api.md
@@ -78,40 +78,33 @@ The Cloud Hypervisor API exposes the following actions through its endpoints:
|
||||
|
||||
#### Virtual Machine (VM) Actions
|
||||
|
||||
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
||||
| ---------------------------------- | ----------------------- | ------------------------------- | ------------------------ | ------------------------------------------------------ |
|
||||
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
|
||||
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
|
||||
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
|
||||
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
|
||||
| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted |
|
||||
| Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted |
|
||||
| Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted |
|
||||
| Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused |
|
||||
| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused |
|
||||
| Perform a coredump of the VM* | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused |
|
||||
| Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted |
|
||||
| Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
|
||||
| Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
|
||||
| Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted |
|
||||
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
|
||||
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add userspace PCI device to the VM | `/vm.add-user-device` | `/schemas/VmAddUserDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted |
|
||||
| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted |
|
||||
| Prepare to receive a migration | `/vm.receive-migration` | `/schemas/ReceiveMigrationData` | N/A | N/A |
|
||||
| Start to send migration to target | `/vm.send-migration` | `/schemas/SendMigrationData` | N/A | The VM is booted and (shared mem or hugepages enabled) |
|
||||
|
||||
* The `vmcoredump` action is available exclusively for the `x86_64`
|
||||
architecture and can be executed only when the `guest_debug` feature is
|
||||
enabled. Without this feature, the corresponding REST API endpoint is not
|
||||
available.
|
||||
| Action | Endpoint | Request Body | Response Body | Prerequisites |
|
||||
| ---------------------------------- | --------------------- | --------------------------- | ------------------------ | -------------------------------- |
|
||||
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
|
||||
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
|
||||
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
|
||||
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
|
||||
| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted |
|
||||
| Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted |
|
||||
| Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted |
|
||||
| Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused |
|
||||
| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused |
|
||||
| Perform a coredump of the VM | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused |
|
||||
| Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted |
|
||||
| Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
|
||||
| Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
|
||||
| Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted |
|
||||
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
|
||||
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add userspace PCI device to the VM | `/vm.add-user-device` | `/schemas/VmAddUserDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted |
|
||||
| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted |
|
||||
|
||||
### REST API Examples
|
||||
|
||||
@@ -228,7 +221,7 @@ The CLI options are parsed by the
|
||||
[internal API](#internal-api) commands.
|
||||
|
||||
The REST API is processed by an HTTP thread using the
|
||||
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/micro-http)
|
||||
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
|
||||
crate. As with the CLI, the HTTP requests eventually get translated into
|
||||
[internal API](#internal-api) commands.
|
||||
|
||||
@@ -386,5 +379,5 @@ APIs work together, let's look at a complete VM creation flow, from the
|
||||
```
|
||||
1. The Cloud Hypervisor HTTP thread sends the formed HTTP response back to the
|
||||
user. This is abstracted by the
|
||||
[micro_http](https://github.com/firecracker-microvm/micro-http)
|
||||
[micro_http](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
|
||||
crate.
|
||||
|
||||
@@ -266,8 +266,11 @@ _Example_
|
||||
|
||||
### `file`
|
||||
|
||||
Path to the file backing the memory zone. The file will be opened and used as
|
||||
the backing file for the `mmap(2)` operation.
|
||||
Path to the file backing the memory zone. This can be either a file or a
|
||||
directory. In case of a file, it will be opened and used as the backing file
|
||||
for the `mmap(2)` operation. In case of a directory, a temporary file with no
|
||||
hard link on the filesystem will be created. This file will be used as the
|
||||
backing file for the `mmap(2)` operation.
|
||||
|
||||
This option can be particularly useful when trying to back a part of the guest
|
||||
RAM with a well known file. In the context of the snapshot/restore feature, and
|
||||
|
||||
@@ -6,5 +6,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.139"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
|
||||
159
fuzz/Cargo.lock
generated
159
fuzz/Cargo.lock
generated
@@ -5,16 +5,16 @@ version = 3
|
||||
[[package]]
|
||||
name = "acpi_tables"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#98dcb0309d362dd83f6ffcac4f66914a2fbd5a73"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#4fd38dd5f746730ec5ae848dafcf8c2f50a13fc3"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.71"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||
|
||||
[[package]]
|
||||
name = "api_client"
|
||||
@@ -25,9 +25,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.3.0"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
|
||||
checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
@@ -76,7 +76,7 @@ dependencies = [
|
||||
"argh_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -143,7 +143,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "31.0.0"
|
||||
version = "29.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
@@ -208,9 +208,9 @@ checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.1"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944"
|
||||
checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
@@ -218,27 +218,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.1"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb"
|
||||
checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.1"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
|
||||
checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -296,9 +296,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.9"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -351,15 +351,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.26"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -393,9 +393,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.144"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
@@ -498,9 +498,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.57"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -518,9 +518,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.27"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -536,13 +536,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "remain"
|
||||
version = "0.2.8"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13cca257d068dd3a390d04b2c3009a3fad2ee5048dfa8f239d048372810470c"
|
||||
checksum = "5704e2cda92fd54202f05430725317ba0ea7d0c96b246ca0a92e45177127ba3b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -556,9 +556,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "seccompiler"
|
||||
@@ -571,35 +571,35 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.163"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.163"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.96"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -608,9 +608,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "2.3.3"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe"
|
||||
checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_with_macros",
|
||||
@@ -618,14 +618,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "2.3.3"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f"
|
||||
checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -665,20 +665,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
version = "1.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||
checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -687,22 +676,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.40"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.40"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -731,24 +720,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.3.3"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
|
||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.1.10"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca4b7062e7e6d685901e815c35f9671e059de97c1c0905eeff8592f3fff442f"
|
||||
checksum = "d6e2495726cf917e7ba7ec8bf0f0fceab543dd38d0a4195ed6bef331e38a290f"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
@@ -756,7 +745,7 @@ dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.109",
|
||||
"syn",
|
||||
"versionize_derive",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
@@ -764,11 +753,11 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "versionize_derive"
|
||||
version = "0.1.4"
|
||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#e502b1d4aabab342386f0c53780d49f21a6a1df6"
|
||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#ae35ef7a3ddabd3371ab8ac0193a383aff6e4b1b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1000,7 +989,6 @@ dependencies = [
|
||||
"vm-migration",
|
||||
"vm-virtio",
|
||||
"vmm-sys-util",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1042,24 +1030,3 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@@ -12,7 +12,7 @@ cargo-fuzz = true
|
||||
block_util = { path = "../block_util" }
|
||||
devices = { path = "../devices" }
|
||||
epoll = "4.3.1"
|
||||
libc = "0.2.144"
|
||||
libc = "0.2.138"
|
||||
libfuzzer-sys = "0.4.6"
|
||||
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
|
||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
||||
|
||||
@@ -6,22 +6,22 @@ edition = "2021"
|
||||
license = "Apache-2.0 OR BSD-3-Clause"
|
||||
|
||||
[features]
|
||||
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
|
||||
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv"]
|
||||
kvm = ["kvm-ioctls", "kvm-bindings"]
|
||||
mshv = ["mshv-ioctls", "mshv-bindings"]
|
||||
tdx = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
byteorder = "1.4.3"
|
||||
thiserror = "1.0.39"
|
||||
thiserror = "1.0.38"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
kvm-ioctls = { version = "0.13.0", optional = true }
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_with = { version = "2.3.2", default-features = false, features = ["macros"] }
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_with = { version = "2.1.0", default-features = false, features = ["macros"] }
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic"] }
|
||||
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||
|
||||
@@ -26,6 +26,7 @@ pub const MTRR_MEM_TYPE_WB: u64 = 0x6;
|
||||
pub const NUM_IOAPIC_PINS: usize = 24;
|
||||
|
||||
// X86 Exceptions
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Exception {
|
||||
DE = 0, // Divide Error
|
||||
|
||||
@@ -133,7 +133,4 @@ pub trait Hypervisor: Send + Sync {
|
||||
fn get_guest_debug_hw_bps(&self) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Get maximum number of vCPUs
|
||||
fn get_max_vcpus(&self) -> u32;
|
||||
}
|
||||
|
||||
@@ -243,6 +243,7 @@ impl KvmGicV3Its {
|
||||
}
|
||||
|
||||
/// Method to initialize the GIC device
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
pub fn new(vm: &dyn Vm, config: VgicConfig) -> Result<KvmGicV3Its> {
|
||||
// This is inside KVM module
|
||||
let vm = vm.as_any().downcast_ref::<KvmVm>().expect("Wrong VM type?");
|
||||
|
||||
@@ -335,17 +335,16 @@ impl KvmVm {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Implementation of Vm trait for KVM
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let kvm = KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(kvm);
|
||||
/// Example:
|
||||
/// #[cfg(feature = "kvm")]
|
||||
/// extern crate hypervisor
|
||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// ```
|
||||
/// vm.set/get().unwrap()
|
||||
///
|
||||
impl vm::Vm for KvmVm {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
@@ -918,16 +917,13 @@ impl KvmHypervisor {
|
||||
}
|
||||
}
|
||||
/// Implementation of Hypervisor trait for KVM
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let kvm = KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(kvm);
|
||||
/// Example:
|
||||
/// #[cfg(feature = "kvm")]
|
||||
/// extern crate hypervisor
|
||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// ```
|
||||
///
|
||||
impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
///
|
||||
/// Returns the type of the hypervisor
|
||||
@@ -936,15 +932,13 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
HypervisorType::Kvm
|
||||
}
|
||||
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// use hypervisor::kvm::KvmVm;
|
||||
/// Example
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::KvmHypervisor;
|
||||
/// use hypervisor::KvmVm;
|
||||
/// let hypervisor = KvmHypervisor::new().unwrap();
|
||||
/// let vm = hypervisor.create_vm_with_type(0).unwrap();
|
||||
/// ```
|
||||
/// let vm = hypervisor.create_vm_with_type(KvmVmType::LegacyVm).unwrap()
|
||||
///
|
||||
fn create_vm_with_type(&self, vm_type: u64) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||
let fd: VmFd;
|
||||
loop {
|
||||
@@ -998,15 +992,13 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
}
|
||||
|
||||
/// Create a KVM vm object and return the object as Vm trait object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// use hypervisor::kvm::KvmVm;
|
||||
/// Example
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::KvmHypervisor;
|
||||
/// use hypervisor::KvmVm;
|
||||
/// let hypervisor = KvmHypervisor::new().unwrap();
|
||||
/// let vm = hypervisor.create_vm().unwrap();
|
||||
/// ```
|
||||
/// let vm = hypervisor.create_vm().unwrap()
|
||||
///
|
||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||
#[allow(unused_mut)]
|
||||
let mut vm_type: u64 = 0; // Create with default platform type
|
||||
@@ -1084,11 +1076,6 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
self.kvm.get_guest_debug_hw_bps() as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Get maximum number of vCPUs
|
||||
fn get_max_vcpus(&self) -> u32 {
|
||||
self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32
|
||||
}
|
||||
}
|
||||
/// Vcpu struct for KVM
|
||||
pub struct KvmVcpu {
|
||||
@@ -1100,17 +1087,15 @@ pub struct KvmVcpu {
|
||||
hyperv_synic: AtomicBool,
|
||||
}
|
||||
/// Implementation of Vcpu trait for KVM
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let kvm = KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(kvm);
|
||||
/// Example:
|
||||
/// #[cfg(feature = "kvm")]
|
||||
/// extern crate hypervisor
|
||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
/// ```
|
||||
/// vcpu.get/set().unwrap()
|
||||
///
|
||||
impl cpu::Vcpu for KvmVcpu {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
@@ -1812,10 +1797,11 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::KvmHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let kvm = KvmHypervisor::new().unwrap();
|
||||
/// let hv = Arc::new(kvm);
|
||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
||||
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
||||
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
||||
/// vm.enable_split_irq().unwrap();
|
||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
@@ -1983,10 +1969,11 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use hypervisor::kvm::KvmHypervisor;
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::KvmHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let kvm = KvmHypervisor::new().unwrap();
|
||||
/// let hv = Arc::new(kvm);
|
||||
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
|
||||
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
|
||||
/// let vm = hv.create_vm().expect("new VM fd creation failed");
|
||||
/// vm.enable_split_irq().unwrap();
|
||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
|
||||
@@ -48,9 +48,9 @@ mod cpu;
|
||||
/// Device related module
|
||||
mod device;
|
||||
|
||||
pub use crate::hypervisor::{Hypervisor, HypervisorError};
|
||||
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
|
||||
pub use device::HypervisorDeviceError;
|
||||
pub use hypervisor::{Hypervisor, HypervisorError};
|
||||
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
|
||||
pub use kvm::{aarch64, GicState};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -195,16 +195,13 @@ impl MshvHypervisor {
|
||||
}
|
||||
}
|
||||
/// Implementation of Hypervisor trait for Mshv
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::mshv::MshvHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let mshv = MshvHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(mshv);
|
||||
/// Example:
|
||||
/// #[cfg(feature = "mshv")]
|
||||
/// extern crate hypervisor
|
||||
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// ```
|
||||
///
|
||||
impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
///
|
||||
/// Returns the type of the hypervisor
|
||||
@@ -213,16 +210,13 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
HypervisorType::Mshv
|
||||
}
|
||||
/// Create a mshv vm object and return the object as Vm trait object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// Example
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::mshv::MshvHypervisor;
|
||||
/// use hypervisor::mshv::MshvVm;
|
||||
/// # use hypervisor::MshvHypervisor;
|
||||
/// use hypervisor::MshvVm;
|
||||
/// let hypervisor = MshvHypervisor::new().unwrap();
|
||||
/// let vm = hypervisor.create_vm().unwrap();
|
||||
/// ```
|
||||
/// let vm = hypervisor.create_vm().unwrap()
|
||||
///
|
||||
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
|
||||
let fd: VmFd;
|
||||
loop {
|
||||
@@ -279,13 +273,6 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
/// Get maximum number of vCPUs
|
||||
fn get_max_vcpus(&self) -> u32 {
|
||||
// TODO: Using HV_MAXIMUM_PROCESSORS would be better
|
||||
// but the ioctl API is limited to u8
|
||||
256
|
||||
}
|
||||
}
|
||||
|
||||
/// Vcpu struct for Microsoft Hypervisor
|
||||
@@ -298,17 +285,15 @@ pub struct MshvVcpu {
|
||||
}
|
||||
|
||||
/// Implementation of Vcpu trait for Microsoft Hypervisor
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use hypervisor::mshv::MshvHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// let mshv = MshvHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(mshv);
|
||||
/// Example:
|
||||
/// #[cfg(feature = "mshv")]
|
||||
/// extern crate hypervisor
|
||||
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// let vcpu = vm.create_vcpu(0, None).unwrap();
|
||||
/// ```
|
||||
/// let vcpu = vm.create_vcpu(0).unwrap();
|
||||
/// vcpu.get/set().unwrap()
|
||||
///
|
||||
impl cpu::Vcpu for MshvVcpu {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
@@ -461,10 +446,10 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
/* Advance RIP and update RAX */
|
||||
let arr_reg_name_value = [
|
||||
(
|
||||
hv_register_name_HV_X64_REGISTER_RIP,
|
||||
hv_x64_register_name_HV_X64_REGISTER_RIP,
|
||||
info.header.rip + insn_len,
|
||||
),
|
||||
(hv_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||
(hv_x64_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||
];
|
||||
set_registers_64!(self.fd, arr_reg_name_value)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
||||
@@ -510,10 +495,10 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
/* Advance RIP and update RAX */
|
||||
let arr_reg_name_value = [
|
||||
(
|
||||
hv_register_name_HV_X64_REGISTER_RIP,
|
||||
hv_x64_register_name_HV_X64_REGISTER_RIP,
|
||||
info.header.rip + insn_len,
|
||||
),
|
||||
(hv_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||
(hv_x64_register_name_HV_X64_REGISTER_RAX, ret_rax),
|
||||
];
|
||||
set_registers_64!(self.fd, arr_reg_name_value)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
||||
@@ -583,14 +568,8 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
///
|
||||
/// X86 specific call to setup the CPUID registers.
|
||||
///
|
||||
fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
|
||||
let cpuid: Vec<mshv_bindings::hv_cpuid_entry> = cpuid.iter().map(|e| (*e).into()).collect();
|
||||
let mshv_cpuid = <CpuId>::from_entries(&cpuid)
|
||||
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
|
||||
|
||||
self.fd
|
||||
.register_intercept_result_cpuid(&mshv_cpuid)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
|
||||
fn set_cpuid2(&self, _cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
@@ -938,17 +917,15 @@ impl MshvVm {
|
||||
|
||||
///
|
||||
/// Implementation of Vm trait for Mshv
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// Example:
|
||||
/// #[cfg(feature = "mshv")]
|
||||
/// # extern crate hypervisor;
|
||||
/// # use hypervisor::mshv::MshvHypervisor;
|
||||
/// # use std::sync::Arc;
|
||||
/// # use hypervisor::MshvHypervisor;
|
||||
/// let mshv = MshvHypervisor::new().unwrap();
|
||||
/// let hypervisor = Arc::new(mshv);
|
||||
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
|
||||
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
|
||||
/// ```
|
||||
/// vm.set/get().unwrap()
|
||||
///
|
||||
impl vm::Vm for MshvVm {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
|
||||
@@ -28,12 +28,10 @@ pub mod inn;
|
||||
// generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust
|
||||
// --constified-enum '*' --with-derive-default
|
||||
pub mod sockios;
|
||||
pub use if_tun::{
|
||||
sock_fprog, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_TAP, IFF_VNET_HDR, TUN_F_CSUM, TUN_F_TSO4,
|
||||
TUN_F_TSO6, TUN_F_TSO_ECN, TUN_F_UFO,
|
||||
};
|
||||
pub use iff::{ifreq, net_device_flags_IFF_UP, setsockopt, sockaddr, AF_INET};
|
||||
pub use inn::sockaddr_in;
|
||||
pub use if_tun::*;
|
||||
pub use iff::*;
|
||||
pub use inn::*;
|
||||
pub use sockios::*;
|
||||
|
||||
pub const TUNTAP: ::std::os::raw::c_uint = 84;
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
net_gen = { path = "../net_gen" }
|
||||
rate_limiter = { path = "../rate_limiter" }
|
||||
serde = "1.0.156"
|
||||
thiserror = "1.0.39"
|
||||
versionize = "0.1.10"
|
||||
serde = "1.0.151"
|
||||
thiserror = "1.0.38"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
virtio-bindings = "0.2.0"
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.11.0"
|
||||
@@ -25,4 +25,4 @@ vmm-sys-util = "0.11.0"
|
||||
once_cell = "1.17.1"
|
||||
pnet = "0.33.0"
|
||||
pnet_datalink = "0.33.0"
|
||||
serde_json = "1.0.96"
|
||||
serde_json = "1.0.93"
|
||||
|
||||
@@ -10,7 +10,7 @@ kvm = ["vfio-ioctls/kvm"]
|
||||
mshv = ["vfio-ioctls/mshv"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
byteorder = "1.4.3"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
||||
@@ -20,9 +20,9 @@ vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
||||
vmm-sys-util = "0.11.0"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
serde = { version = "1.0.156", features = ["derive"] }
|
||||
thiserror = "1.0.39"
|
||||
versionize = "0.1.10"
|
||||
serde = { version = "1.0.151", features = ["derive"] }
|
||||
thiserror = "1.0.38"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
|
||||
@@ -511,16 +511,6 @@ impl MsixCap {
|
||||
self.pba & 0xffff_fff8
|
||||
}
|
||||
|
||||
pub fn table_set_offset(&mut self, addr: u32) {
|
||||
self.table &= 0x7;
|
||||
self.table += addr;
|
||||
}
|
||||
|
||||
pub fn pba_set_offset(&mut self, addr: u32) {
|
||||
self.pba &= 0x7;
|
||||
self.pba += addr;
|
||||
}
|
||||
|
||||
pub fn table_bir(&self) -> u32 {
|
||||
self.table & 0x7
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ use crate::{
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use hypervisor::HypervisorVmError;
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
use std::any::Any;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io;
|
||||
@@ -28,9 +27,6 @@ use vfio_bindings::bindings::vfio::*;
|
||||
use vfio_ioctls::{
|
||||
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
|
||||
};
|
||||
use vm_allocator::page_size::{
|
||||
align_page_size_down, align_page_size_up, is_4k_aligned, is_4k_multiple, is_page_size_aligned,
|
||||
};
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
||||
@@ -502,29 +498,6 @@ impl VfioCommon {
|
||||
Ok(vfio_common)
|
||||
}
|
||||
|
||||
/// In case msix table offset is not page size aligned, we need do some fixup to achive it.
|
||||
/// Becuse we don't want the MMIO RW region and trap region overlap each other.
|
||||
fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
|
||||
let msix = self.interrupt.msix.as_mut().unwrap();
|
||||
let msix_cap = &mut msix.cap;
|
||||
|
||||
// Suppose table_bir equals to pba_bir here. Am I right?
|
||||
let (table_offset, table_size) = msix_cap.table_range();
|
||||
if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id {
|
||||
return region_size;
|
||||
}
|
||||
|
||||
let (pba_offset, pba_size) = msix_cap.pba_range();
|
||||
let msix_sz = align_page_size_up(table_size + pba_size);
|
||||
// Expand region to hold RW and trap region which both page size aligned
|
||||
let size = std::cmp::max(region_size * 2, msix_sz * 2);
|
||||
// let table starts from the middle of the region
|
||||
msix_cap.table_set_offset((size / 2) as u32);
|
||||
msix_cap.pba_set_offset((size / 2 + pba_offset - table_offset) as u32);
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
pub(crate) fn allocate_bars(
|
||||
&mut self,
|
||||
allocator: &Arc<Mutex<SystemAllocator>>,
|
||||
@@ -688,16 +661,9 @@ impl VfioCommon {
|
||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
||||
}
|
||||
PciBarRegionType::Memory64BitRegion => {
|
||||
// We need do some fixup to keep MMIO RW region and msix cap region page size
|
||||
// aligned.
|
||||
region_size = self.fixup_msix_region(bar_id, region_size);
|
||||
// BAR allocation must be naturally aligned
|
||||
mmio_allocator
|
||||
.allocate(
|
||||
restored_bar_addr,
|
||||
region_size,
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
Some(unsafe { sysconf(_SC_PAGESIZE) as GuestUsize }),
|
||||
)
|
||||
.allocate(restored_bar_addr, region_size, Some(region_size))
|
||||
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
|
||||
}
|
||||
};
|
||||
@@ -834,23 +800,6 @@ impl VfioCommon {
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn get_msix_cap_idx(&self) -> Option<usize> {
|
||||
let mut cap_next = self
|
||||
.vfio_wrapper
|
||||
.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
|
||||
|
||||
while cap_next != 0 {
|
||||
let cap_id = self.vfio_wrapper.read_config_byte(cap_next.into());
|
||||
if PciCapabilityId::from(cap_id) == PciCapabilityId::MsiX {
|
||||
return Some(cap_next as usize);
|
||||
} else {
|
||||
cap_next = self.vfio_wrapper.read_config_byte((cap_next + 1).into());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn parse_capabilities(&mut self, bdf: PciBdf) {
|
||||
let mut cap_next = self
|
||||
.vfio_wrapper
|
||||
@@ -1205,15 +1154,6 @@ impl VfioCommon {
|
||||
return self.configuration.read_reg(reg_idx);
|
||||
}
|
||||
|
||||
if let Some(id) = self.get_msix_cap_idx() {
|
||||
let msix = self.interrupt.msix.as_mut().unwrap();
|
||||
if reg_idx * 4 == id + 4 {
|
||||
return msix.cap.table;
|
||||
} else if reg_idx * 4 == id + 8 {
|
||||
return msix.cap.pba;
|
||||
}
|
||||
}
|
||||
|
||||
// Since we don't support passing multi-functions devices, we should
|
||||
// mask the multi-function bit, bit 7 of the Header Type byte on the
|
||||
// register 3.
|
||||
@@ -1376,6 +1316,18 @@ impl VfioPciDevice {
|
||||
self.iommu_attached
|
||||
}
|
||||
|
||||
fn align_4k(address: u64) -> u64 {
|
||||
(address + 0xfff) & 0xffff_ffff_ffff_f000
|
||||
}
|
||||
|
||||
fn is_4k_aligned(address: u64) -> bool {
|
||||
(address & 0xfff) == 0
|
||||
}
|
||||
|
||||
fn is_4k_multiple(size: u64) -> bool {
|
||||
(size & 0xfff) == 0
|
||||
}
|
||||
|
||||
fn generate_sparse_areas(
|
||||
caps: &[VfioRegionInfoCap],
|
||||
region_index: u32,
|
||||
@@ -1387,14 +1339,14 @@ impl VfioPciDevice {
|
||||
match cap {
|
||||
VfioRegionInfoCap::SparseMmap(sparse_mmap) => return Ok(sparse_mmap.areas.clone()),
|
||||
VfioRegionInfoCap::MsixMappable => {
|
||||
if !is_4k_aligned(region_start) {
|
||||
if !Self::is_4k_aligned(region_start) {
|
||||
error!(
|
||||
"Region start address 0x{:x} must be at least aligned on 4KiB",
|
||||
region_start
|
||||
);
|
||||
return Err(VfioPciError::RegionAlignment);
|
||||
}
|
||||
if !is_4k_multiple(region_size) {
|
||||
if !Self::is_4k_multiple(region_size) {
|
||||
error!(
|
||||
"Region size 0x{:x} must be at least a multiple of 4KiB",
|
||||
region_size
|
||||
@@ -1406,8 +1358,7 @@ impl VfioPciDevice {
|
||||
// the MSI-X PBA table, we must calculate the subregions
|
||||
// around them, leading to a list of sparse areas.
|
||||
// We want to make sure we will still trap MMIO accesses
|
||||
// to these MSI-X specific ranges. If these region don't align
|
||||
// with pagesize, we can achive it by enlarging its range.
|
||||
// to these MSI-X specific ranges.
|
||||
//
|
||||
// Using a BtreeMap as the list provided through the iterator is sorted
|
||||
// by key. This ensures proper split of the whole region.
|
||||
@@ -1415,14 +1366,10 @@ impl VfioPciDevice {
|
||||
if let Some(msix) = vfio_msix {
|
||||
if region_index == msix.cap.table_bir() {
|
||||
let (offset, size) = msix.cap.table_range();
|
||||
let offset = align_page_size_down(offset);
|
||||
let size = align_page_size_up(size);
|
||||
inter_ranges.insert(offset, size);
|
||||
}
|
||||
if region_index == msix.cap.pba_bir() {
|
||||
let (offset, size) = msix.cap.pba_range();
|
||||
let offset = align_page_size_down(offset);
|
||||
let size = align_page_size_up(size);
|
||||
inter_ranges.insert(offset, size);
|
||||
}
|
||||
}
|
||||
@@ -1436,7 +1383,8 @@ impl VfioPciDevice {
|
||||
size: range_offset - current_offset,
|
||||
});
|
||||
}
|
||||
current_offset = align_page_size_down(range_offset + range_size);
|
||||
|
||||
current_offset = Self::align_4k(range_offset + range_size);
|
||||
}
|
||||
|
||||
if region_size > current_offset {
|
||||
@@ -1534,15 +1482,6 @@ impl VfioPciDevice {
|
||||
return Err(VfioPciError::MmapArea);
|
||||
}
|
||||
|
||||
if !is_page_size_aligned(area.size) || !is_page_size_aligned(area.offset) {
|
||||
warn!(
|
||||
"Could not mmap sparse area that is not page size aligned (offset = 0x{:x}, size = 0x{:x})",
|
||||
area.offset,
|
||||
area.size,
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let user_memory_region = UserMemoryRegion {
|
||||
slot: (self.memory_slot)(),
|
||||
start: region.start.0 + area.offset,
|
||||
|
||||
@@ -7,9 +7,9 @@ build = "../build.rs"
|
||||
|
||||
[dependencies]
|
||||
argh = "0.1.9"
|
||||
dirs = "5.0.0"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
dirs = "4.0.0"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
test_infra = { path = "../test_infra" }
|
||||
thiserror = "1.0.39"
|
||||
thiserror = "1.0.38"
|
||||
wait-timeout = "0.2.0"
|
||||
|
||||
@@ -110,23 +110,18 @@ impl Default for MetricsReport {
|
||||
#[derive(Default)]
|
||||
pub struct PerformanceTestOverrides {
|
||||
test_iterations: Option<u32>,
|
||||
test_timeout: Option<u32>,
|
||||
}
|
||||
|
||||
impl fmt::Display for PerformanceTestOverrides {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if let Some(test_iterations) = self.test_iterations {
|
||||
write!(f, "test_iterations = {test_iterations}, ")?;
|
||||
}
|
||||
if let Some(test_timeout) = self.test_timeout {
|
||||
write!(f, "test_timeout = {test_timeout}")?;
|
||||
write!(f, "test_iterations = {test_iterations}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PerformanceTestControl {
|
||||
test_timeout: u32,
|
||||
test_iterations: u32,
|
||||
@@ -193,14 +188,7 @@ impl PerformanceTest {
|
||||
.test_iterations
|
||||
.unwrap_or(self.control.test_iterations)
|
||||
{
|
||||
// update the timeout in control if passed explicitly and run testcase with it
|
||||
if let Some(test_timeout) = overrides.test_timeout {
|
||||
let mut control: PerformanceTestControl = self.control.clone();
|
||||
control.test_timeout = test_timeout;
|
||||
metrics.push((self.func_ptr)(&control));
|
||||
} else {
|
||||
metrics.push((self.func_ptr)(&self.control));
|
||||
}
|
||||
metrics.push((self.func_ptr)(&self.control));
|
||||
}
|
||||
|
||||
let mean = (self.unit_adjuster)(mean(&metrics).unwrap());
|
||||
@@ -219,9 +207,9 @@ impl PerformanceTest {
|
||||
|
||||
// Calculate the timeout for each test
|
||||
// Note: To cover the setup/cleanup time, 20s is added for each iteration of the test
|
||||
pub fn calc_timeout(&self, test_iterations: &Option<u32>, test_timeout: &Option<u32>) -> u64 {
|
||||
((test_timeout.unwrap_or(self.control.test_timeout) + 20)
|
||||
* test_iterations.unwrap_or(self.control.test_iterations)) as u64
|
||||
pub fn calc_timeout(&self, test_iterations: &Option<u32>) -> u64 {
|
||||
((self.control.test_timeout + 20) * test_iterations.unwrap_or(self.control.test_iterations))
|
||||
as u64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,7 +587,6 @@ fn run_test_with_timeout(
|
||||
) -> Result<PerformanceTestResult, Error> {
|
||||
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
|
||||
let test_iterations = overrides.test_iterations;
|
||||
let test_timeout = overrides.test_timeout;
|
||||
let overrides = overrides.clone();
|
||||
thread::spawn(move || {
|
||||
println!(
|
||||
@@ -622,7 +609,7 @@ fn run_test_with_timeout(
|
||||
});
|
||||
|
||||
// Todo: Need to cleanup/kill all hanging child processes
|
||||
let test_timeout = test.calc_timeout(&test_iterations, &test_timeout);
|
||||
let test_timeout = test.calc_timeout(&test_iterations);
|
||||
receiver
|
||||
.recv_timeout(Duration::from_secs(test_timeout))
|
||||
.map_err(|_| {
|
||||
@@ -658,10 +645,6 @@ struct Options {
|
||||
/// override number of test iterations
|
||||
iterations: Option<u32>,
|
||||
|
||||
#[argh(option, long = "timeout")]
|
||||
/// override test timeout, Ex. --timeout 5
|
||||
timeout: Option<u32>,
|
||||
|
||||
#[argh(switch, short = 'V', long = "version")]
|
||||
/// print version information
|
||||
version: bool,
|
||||
@@ -671,7 +654,7 @@ fn main() {
|
||||
let opts: Options = argh::from_env();
|
||||
|
||||
if opts.version {
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -700,7 +683,6 @@ fn main() {
|
||||
|
||||
let overrides = Arc::new(PerformanceTestOverrides {
|
||||
test_iterations: opts.iterations,
|
||||
test_timeout: opts.timeout,
|
||||
});
|
||||
|
||||
for test in test_list.iter() {
|
||||
|
||||
@@ -66,7 +66,7 @@ impl QcowRawFile {
|
||||
non_zero_flags: u64,
|
||||
) -> io::Result<()> {
|
||||
self.file.seek(SeekFrom::Start(offset))?;
|
||||
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
|
||||
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u64>(), &mut self.file);
|
||||
for addr in table {
|
||||
let val = if *addr == 0 {
|
||||
0
|
||||
@@ -91,8 +91,7 @@ impl QcowRawFile {
|
||||
/// Writes a refcount block to the file.
|
||||
pub fn write_refcount_block(&mut self, offset: u64, table: &[u16]) -> io::Result<()> {
|
||||
self.file.seek(SeekFrom::Start(offset))?;
|
||||
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
|
||||
|
||||
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u16>(), &mut self.file);
|
||||
for count in table {
|
||||
buffer.write_u16::<BigEndian>(*count)?;
|
||||
}
|
||||
|
||||
244
release-notes.md
244
release-notes.md
@@ -1,25 +1,11 @@
|
||||
- [v32.1](#v321)
|
||||
- [v32.0](#v320)
|
||||
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
||||
- [API Changes](#api-changes)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [v31.1](#v311)
|
||||
- [v31.0](#v310)
|
||||
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
||||
- [Update Reference Kernel to 6.2](#update-reference-kernel-to-62)
|
||||
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
|
||||
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
|
||||
- [Documentation Improvements](#documentation-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Contributors](#contributors-1)
|
||||
- [v30.1](#v301)
|
||||
- [v30.0](#v300)
|
||||
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
||||
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
||||
- [Heap Profiling Support](#heap-profiling-support)
|
||||
- [Documentation Improvements](#documentation-improvements-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Contributors](#contributors-2)
|
||||
- [Documentation Improvements](#documentation-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [v28.2](#v282)
|
||||
- [v29.0](#v290)
|
||||
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
||||
@@ -29,10 +15,10 @@
|
||||
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
||||
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
||||
- [TCP Offload Control](#tcp-offload-control)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Removals](#removals)
|
||||
- [Deprecations](#deprecations)
|
||||
- [Contributors](#contributors-3)
|
||||
- [Contributors](#contributors-1)
|
||||
- [v28.1](#v281)
|
||||
- [v28.0](#v280)
|
||||
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
||||
@@ -40,9 +26,9 @@
|
||||
- [Virtualised TPM Support](#virtualised-tpm-support)
|
||||
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
||||
- [README Quick Start Improved](#readme-quick-start-improved)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Removals](#removals-1)
|
||||
- [Contributors](#contributors-4)
|
||||
- [Contributors](#contributors-2)
|
||||
- [v27.0](#v270)
|
||||
- [Community Engagement](#community-engagement)
|
||||
- [Prebuilt Packages](#prebuilt-packages)
|
||||
@@ -51,41 +37,41 @@
|
||||
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
||||
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
||||
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Deprecations](#deprecations-1)
|
||||
- [Contributors](#contributors-5)
|
||||
- [Contributors](#contributors-3)
|
||||
- [v26.0](#v260)
|
||||
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
|
||||
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via-platform)
|
||||
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Deprecations](#deprecations-2)
|
||||
- [Removals](#removals-2)
|
||||
- [Contributors](#contributors-6)
|
||||
- [Contributors](#contributors-4)
|
||||
- [v25.0](#v250)
|
||||
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
||||
- [VM "Coredump" Support](#vm-coredump-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Removals](#removals-3)
|
||||
- [Contributors](#contributors-7)
|
||||
- [Contributors](#contributors-5)
|
||||
- [v24.0](#v240)
|
||||
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
||||
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
||||
- [Sparse Mmap support](#sparse-mmap-support)
|
||||
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Notable Improvements](#notable-improvements)
|
||||
- [Deprecations](#deprecations-3)
|
||||
- [New on the Website](#new-on-the-website)
|
||||
- [Contributors](#contributors-8)
|
||||
- [Contributors](#contributors-6)
|
||||
- [v23.1](#v231)
|
||||
- [v23.0](#v230)
|
||||
- [vDPA Support](#vdpa-support)
|
||||
- [Updated OS Support list](#updated-os-support-list)
|
||||
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
||||
- [`AMX` Support](#amx-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Deprecations](#deprecations-4)
|
||||
- [Contributors](#contributors-9)
|
||||
- [Contributors](#contributors-7)
|
||||
- [v22.1](#v221)
|
||||
- [v22.0](#v220)
|
||||
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
||||
@@ -96,13 +82,13 @@
|
||||
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
||||
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
||||
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||
- [Contributors](#contributors-10)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Contributors](#contributors-8)
|
||||
- [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-11)
|
||||
- [Contributors](#contributors-11)
|
||||
- [Notable Bug fixes](#notable-bug-fixes-9)
|
||||
- [Contributors](#contributors-9)
|
||||
- [v20.2](#v202)
|
||||
- [v20.1](#v201)
|
||||
- [v20.0](#v200)
|
||||
@@ -111,8 +97,8 @@
|
||||
- [Improved VFIO support](#improved-vfio-support)
|
||||
- [Safer code](#safer-code)
|
||||
- [Extended documentation](#extended-documentation)
|
||||
- [Notable bug fixes](#notable-bug-fixes-12)
|
||||
- [Contributors](#contributors-12)
|
||||
- [Notable bug fixes](#notable-bug-fixes-10)
|
||||
- [Contributors](#contributors-10)
|
||||
- [v19.0](#v190)
|
||||
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
|
||||
- [PCI boot time optimisations](#pci-boot-time-optimisations)
|
||||
@@ -120,8 +106,8 @@
|
||||
- [Live migration enhancements](#live-migration-enhancements)
|
||||
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
|
||||
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
|
||||
- [Notable bug fixes](#notable-bug-fixes-13)
|
||||
- [Contributors](#contributors-13)
|
||||
- [Notable bug fixes](#notable-bug-fixes-11)
|
||||
- [Contributors](#contributors-11)
|
||||
- [v18.0](#v180)
|
||||
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
|
||||
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
|
||||
@@ -131,31 +117,31 @@
|
||||
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
||||
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
||||
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
||||
- [Notable bug fixes](#notable-bug-fixes-14)
|
||||
- [Contributors](#contributors-14)
|
||||
- [Notable bug fixes](#notable-bug-fixes-12)
|
||||
- [Contributors](#contributors-12)
|
||||
- [v17.0](#v170)
|
||||
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
|
||||
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
|
||||
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
|
||||
- [Improved SGX support](#improved-sgx-support)
|
||||
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
|
||||
- [Notable bug fixes](#notable-bug-fixes-15)
|
||||
- [Contributors](#contributors-15)
|
||||
- [Notable bug fixes](#notable-bug-fixes-13)
|
||||
- [Contributors](#contributors-13)
|
||||
- [v16.0](#v160)
|
||||
- [Improved live migration support](#improved-live-migration-support)
|
||||
- [Improved `vhost-user` support](#improved-vhost-user-support)
|
||||
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
|
||||
- [Notable bug fixes](#notable-bug-fixes-16)
|
||||
- [Notable bug fixes](#notable-bug-fixes-14)
|
||||
- [Removed functionality](#removed-functionality)
|
||||
- [Contributors](#contributors-16)
|
||||
- [Contributors](#contributors-14)
|
||||
- [v15.0](#v150)
|
||||
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
||||
- [Network device rate limiting](#network-device-rate-limiting)
|
||||
- [Support for runtime control of `virtio-net` guest offload](#support-for-runtime-control-of-virtio-net-guest-offload)
|
||||
- [`--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)
|
||||
- [Deprecations](#deprecations-5)
|
||||
- [Contributors](#contributors-17)
|
||||
- [Contributors](#contributors-15)
|
||||
- [v0.14.1](#v0141)
|
||||
- [v0.14.0](#v0140)
|
||||
- [Structured event monitoring](#structured-event-monitoring)
|
||||
@@ -165,7 +151,7 @@
|
||||
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
||||
- [Block device rate limiting](#block-device-rate-limiting)
|
||||
- [Deprecations](#deprecations-6)
|
||||
- [Contributors](#contributors-18)
|
||||
- [Contributors](#contributors-16)
|
||||
- [v0.13.0](#v0130)
|
||||
- [Wider VFIO device support](#wider-vfio-device-support)
|
||||
- [Improved huge page support](#improved-huge-page-support)
|
||||
@@ -173,13 +159,13 @@
|
||||
- [VHD disk image support](#vhd-disk-image-support)
|
||||
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
||||
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
||||
- [Contributors](#contributors-19)
|
||||
- [Contributors](#contributors-17)
|
||||
- [v0.12.0](#v0120)
|
||||
- [ARM64 enhancements](#arm64-enhancements)
|
||||
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
|
||||
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
|
||||
- [Enhanced "info" API](#enhanced-info-api)
|
||||
- [Contributors](#contributors-20)
|
||||
- [Contributors](#contributors-18)
|
||||
- [v0.11.0](#v0110)
|
||||
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
||||
- [Windows Guest Support](#windows-guest-support)
|
||||
@@ -189,17 +175,17 @@
|
||||
- [Improved Linux Boot Time](#improved-linux-boot-time)
|
||||
- [`SIGTERM/SIGINT` Interrupt Signal Handling](#sigtermsigint-interrupt-signal-handling)
|
||||
- [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)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-17)
|
||||
- [Contributors](#contributors-21)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-15)
|
||||
- [Contributors](#contributors-19)
|
||||
- [v0.10.0](#v0100)
|
||||
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
||||
- [Memory Zones](#memory-zones)
|
||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
||||
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-18)
|
||||
- [Contributors](#contributors-22)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-16)
|
||||
- [Contributors](#contributors-20)
|
||||
- [v0.9.0](#v090)
|
||||
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
||||
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
||||
@@ -212,17 +198,17 @@
|
||||
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
||||
- [Intel SGX Support](#intel-sgx-support)
|
||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-19)
|
||||
- [Contributors](#contributors-23)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-17)
|
||||
- [Contributors](#contributors-21)
|
||||
- [v0.8.0](#v080)
|
||||
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
||||
- [Experimental ARM64 Support](#experimental-arm64-support)
|
||||
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
|
||||
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
|
||||
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-20)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-18)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||
- [Contributors](#contributors-24)
|
||||
- [Contributors](#contributors-22)
|
||||
- [v0.7.0](#v070)
|
||||
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
||||
- [Alternative `libc` Support](#alternative-libc-support)
|
||||
@@ -232,14 +218,14 @@
|
||||
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
||||
- [Updated Distribution Support](#updated-distribution-support)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
||||
- [Contributors](#contributors-25)
|
||||
- [Contributors](#contributors-23)
|
||||
- [v0.6.0](#v060)
|
||||
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
||||
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
||||
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
||||
- [Command Line Interface](#command-line-interface)
|
||||
- [PVH Boot](#pvh-boot)
|
||||
- [Contributors](#contributors-26)
|
||||
- [Contributors](#contributors-24)
|
||||
- [v0.5.1](#v051)
|
||||
- [v0.5.0](#v050)
|
||||
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
||||
@@ -247,7 +233,7 @@
|
||||
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
||||
- [Development Tools](#development-tools)
|
||||
- [Kata Containers Integration](#kata-containers-integration)
|
||||
- [Contributors](#contributors-27)
|
||||
- [Contributors](#contributors-25)
|
||||
- [v0.4.0](#v040)
|
||||
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
||||
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
||||
@@ -256,7 +242,7 @@
|
||||
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
||||
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
||||
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
||||
- [Contributors](#contributors-28)
|
||||
- [Contributors](#contributors-26)
|
||||
- [v0.3.0](#v030)
|
||||
- [Block device offloading](#block-device-offloading)
|
||||
- [Network device backend](#network-device-backend)
|
||||
@@ -283,63 +269,7 @@
|
||||
- [Unit testing](#unit-testing)
|
||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||
|
||||
# v32.1
|
||||
|
||||
This is a bug fix release. The following issues have been addressed:
|
||||
|
||||
* Report errors explicitly to users when VM failed to boot (#5453)
|
||||
* Fix VFIO on platforms with non-4k page size (#5450, #5469)
|
||||
* Fix TDX initialization (#5454)
|
||||
* Ensure all guest memory regions are page-size aligned (#5496)
|
||||
* Fix seccomp filter lists related to virtio-console, serial and pty
|
||||
(#5506, #5524)
|
||||
* Populate APIC ID properly (#5512)
|
||||
* Ignore and warn TAP FDs in more situations (#5522)
|
||||
|
||||
# v32.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||
v32.0. The following user visible changes have been made:
|
||||
|
||||
### Increased PCI Segment Limit
|
||||
|
||||
The maximum number of PCI segments that can be used is now 96 (up from 16).
|
||||
|
||||
### API Changes
|
||||
|
||||
* The VmmPingResponse now includes the PID as well as the build details.
|
||||
(#5348)
|
||||
|
||||
### Notable Bug Fixes
|
||||
|
||||
* Ignore and warn TAP FDs sent via the HTTP request body (#5350)
|
||||
* Properly preserve and close valid FDs for TAP devices (#5373)
|
||||
* Only use `KVM_ARM_VCPU_PMU_V3` if available (#5360)
|
||||
* Only touch the tty flags if it's being used (#5343)
|
||||
* Fix seccomp filter lists for vhost-user devices (#5361)
|
||||
* The number of vCPUs is capped at the hypervisor maximum (#5357)
|
||||
* Fixes for TTY reset (#5414)
|
||||
* CPU topology fixes on MSHV (#5325)
|
||||
* Seccomp fixes for older distributions (#5397)
|
||||
|
||||
### Contributors
|
||||
|
||||
Many thanks to everyone who has contributed to our release:
|
||||
|
||||
* Alyssa Ross <hi@alyssa.is>
|
||||
* Anatol Belski <anbelski@linux.microsoft.com>
|
||||
* Bo Chen <chen.bo@intel.com>
|
||||
* Hao Xu <howeyxu@tencent.com>
|
||||
* Muminul Islam <muislam@microsoft.com>
|
||||
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||
* Rafael Mendonca <rafaelmendsr@gmail.com>
|
||||
* Rob Bradford <rbradford@rivosinc.com>
|
||||
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||
* Smit Gardhariya <gardhariya.smit@gmail.com>
|
||||
* Wei Liu <liuwe@microsoft.com>
|
||||
|
||||
# v31.1
|
||||
# v30.1
|
||||
|
||||
This is a bug fix release. The following issues have been addressed:
|
||||
|
||||
@@ -348,72 +278,10 @@ This is a bug fix release. The following issues have been addressed:
|
||||
* Only use `KVM_ARM_VCPU_PMU_V3` if available (#5360)
|
||||
* Only touch the tty flags if it's being used (#5343)
|
||||
* Fix seccomp filter lists for vhost-user devices (#5361)
|
||||
|
||||
# v31.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||
v31.0. The following user visible changes have been made:
|
||||
|
||||
### Update to Latest `acpi_tables`
|
||||
|
||||
Adapted to the latest [acpi_tables](https://github.com/rust-vmm/acpi_tables).
|
||||
There has been significant API changes in the crate.
|
||||
|
||||
### Update Reference Kernel to 6.2
|
||||
|
||||
Updated the recommended guest kernel version from 6.1.6 to 6.2.
|
||||
|
||||
### Improvements on Console `SIGWINCH` Handler
|
||||
|
||||
A separate thread had been created to capture the `SIGWINCH` signal and resize
|
||||
the guest console. Now the thread is skipped if the console is not resizable.
|
||||
|
||||
Two completely different code paths existed for handling console resizing, one
|
||||
for `tty` and the other for `pty`. That makes the understanding of the console
|
||||
handling code unnecessarily complicated. Now the code paths are unified. Both
|
||||
`tty` and `pty` are supported in single `SIGWINCH` handler. And the new handler
|
||||
can works with kernel versions earlier than v5.5.
|
||||
|
||||
### Remove Directory Support from `MemoryZoneConfig::file`
|
||||
|
||||
Setting a directory to `MemoryZoneConfig::file` is no longer supported.
|
||||
|
||||
Before this change, user can set a directory to `file` of the `--memory-zone`
|
||||
option. In that case, a temporary file will be created as the backing file for
|
||||
the `mmap(2)` operation. This functionality has been unnecessary since we had
|
||||
the native support for hugepages and allocating anonymous shared memory.
|
||||
|
||||
### Documentation Improvements
|
||||
|
||||
* Various improvements in API document
|
||||
* Improvements in Doc comments
|
||||
* Updated Slack channel information in README
|
||||
|
||||
### Notable Bug Fixes
|
||||
|
||||
* Fixed the offset setting while removing the entire mapping of `vhost-user` FS
|
||||
client.
|
||||
* Fixed the `ShutdownVmm` and `Shutdown` commands to call the correct API
|
||||
endpoint.
|
||||
|
||||
### Contributors
|
||||
|
||||
Many thanks to everyone who has contributed to our release:
|
||||
|
||||
* Alyssa Ross <hi@alyssa.is>
|
||||
* Bo Chen <chen.bo@intel.com>
|
||||
* Daniel Farina <daniel@fdr.io>
|
||||
* Dom <peng6662001@163.com>
|
||||
* Hao Xu <howeyxu@tencent.com>
|
||||
* Muminul Islam <muislam@microsoft.com>
|
||||
* Omer Faruk Bayram <omer.faruk@sartura.hr>
|
||||
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||
* Rob Bradford <rbradford@rivosinc.com>
|
||||
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||
* Smit Gardhariya <gardhariya.smit@gmail.com>
|
||||
* Yang <ailin.yang@intel.com>
|
||||
* Yong He <alexyonghe@tencent.com>
|
||||
* Fix the offset setting while removing the entire mapping of
|
||||
`vhost-user` FS client (#5235)
|
||||
* Fix the `ShutdownVmm` and `Shutdown` commands to call the correct API
|
||||
endpoint (#5322)
|
||||
|
||||
# v30.0
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# When changing this file don't forget to update the tag name in the
|
||||
# .github/workflows/docker-image.yaml file if doing multiple per day
|
||||
|
||||
FROM ubuntu:20.04 as dev
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG RUST_TOOLCHAIN="1.67.1"
|
||||
ARG RUST_TOOLCHAIN="1.66.1"
|
||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/arm64 6.2.0 Kernel Configuration
|
||||
# Linux/arm64 6.1.6 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
|
||||
CONFIG_CC_IS_GCC=y
|
||||
@@ -55,6 +55,7 @@ CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_GENERIC_IRQ_IPI=y
|
||||
CONFIG_GENERIC_MSI_IRQ=y
|
||||
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_MSI_IOMMU=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
@@ -202,7 +203,6 @@ CONFIG_INITRAMFS_PRESERVE_MTIME=y
|
||||
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_LD_ORPHAN_WARN=y
|
||||
CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
CONFIG_EXPERT=y
|
||||
@@ -227,7 +227,6 @@ CONFIG_IO_URING=y
|
||||
CONFIG_ADVISE_SYSCALLS=y
|
||||
CONFIG_MEMBARRIER=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_SELFTEST is not set
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
||||
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
|
||||
@@ -250,7 +249,7 @@ CONFIG_PERF_EVENTS=y
|
||||
# end of General setup
|
||||
|
||||
CONFIG_ARM64=y
|
||||
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_MMU=y
|
||||
CONFIG_ARM64_PAGE_SHIFT=12
|
||||
@@ -350,7 +349,6 @@ CONFIG_ARM64_ERRATUM_2054223=y
|
||||
CONFIG_ARM64_ERRATUM_2067961=y
|
||||
CONFIG_ARM64_ERRATUM_2441009=y
|
||||
CONFIG_ARM64_ERRATUM_2457168=y
|
||||
CONFIG_ARM64_ERRATUM_2645198=y
|
||||
CONFIG_CAVIUM_ERRATUM_22375=y
|
||||
CONFIG_CAVIUM_ERRATUM_23144=y
|
||||
CONFIG_CAVIUM_ERRATUM_23154=y
|
||||
@@ -378,7 +376,7 @@ CONFIG_ARM64_PA_BITS=48
|
||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_SCHED_MC=y
|
||||
# CONFIG_SCHED_CLUSTER is not set
|
||||
CONFIG_SCHED_CLUSTER is not set
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_NR_CPUS=128
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
@@ -473,6 +471,7 @@ CONFIG_RANDOMIZE_BASE=y
|
||||
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
|
||||
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
||||
CONFIG_STACKPROTECTOR_PER_TASK=y
|
||||
CONFIG_ARCH_NR_GPIO=0
|
||||
# end of Kernel Features
|
||||
|
||||
#
|
||||
@@ -560,7 +559,6 @@ CONFIG_ACPI_GENERIC_GSI=y
|
||||
CONFIG_ACPI_CCA_REQUIRED=y
|
||||
# CONFIG_ACPI_DEBUGGER is not set
|
||||
CONFIG_ACPI_SPCR_TABLE=y
|
||||
# CONFIG_ACPI_FPDT is not set
|
||||
# CONFIG_ACPI_EC_DEBUGFS is not set
|
||||
# CONFIG_ACPI_AC is not set
|
||||
# CONFIG_ACPI_BATTERY is not set
|
||||
@@ -593,10 +591,8 @@ CONFIG_HAVE_ACPI_APEI=y
|
||||
# CONFIG_ACPI_PFRUT is not set
|
||||
CONFIG_ACPI_IORT=y
|
||||
CONFIG_ACPI_GTDT=y
|
||||
CONFIG_ACPI_APMT=y
|
||||
CONFIG_ACPI_PPTT=y
|
||||
# CONFIG_ACPI_PCC is not set
|
||||
# CONFIG_ACPI_FFH is not set
|
||||
# CONFIG_PMIC_OPREGION is not set
|
||||
CONFIG_ACPI_VIOT=y
|
||||
# CONFIG_ACPI_PRMT is not set
|
||||
@@ -605,9 +601,6 @@ CONFIG_HAVE_KVM=y
|
||||
CONFIG_HAVE_KVM_IRQCHIP=y
|
||||
CONFIG_HAVE_KVM_IRQFD=y
|
||||
CONFIG_HAVE_KVM_IRQ_ROUTING=y
|
||||
CONFIG_HAVE_KVM_DIRTY_RING=y
|
||||
CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y
|
||||
CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y
|
||||
CONFIG_HAVE_KVM_EVENTFD=y
|
||||
CONFIG_KVM_MMIO=y
|
||||
CONFIG_HAVE_KVM_MSI=y
|
||||
@@ -661,7 +654,6 @@ CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
|
||||
CONFIG_MMU_GATHER_TABLE_FREE=y
|
||||
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
||||
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
||||
CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y
|
||||
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
||||
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
||||
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
||||
@@ -726,7 +718,6 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
|
||||
# end of GCOV-based kernel profiling
|
||||
|
||||
CONFIG_HAVE_GCC_PLUGINS=y
|
||||
CONFIG_FUNCTION_ALIGNMENT=0
|
||||
# end of General architecture-dependent options
|
||||
|
||||
CONFIG_RT_MUTEXES=y
|
||||
@@ -893,8 +884,7 @@ CONFIG_ZSMALLOC_STAT=y
|
||||
#
|
||||
# CONFIG_SLAB is not set
|
||||
CONFIG_SLUB=y
|
||||
# CONFIG_SLOB_DEPRECATED is not set
|
||||
# CONFIG_SLUB_TINY is not set
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_SLAB_MERGE_DEFAULT=y
|
||||
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
||||
CONFIG_SLAB_FREELIST_HARDENED=y
|
||||
@@ -961,7 +951,6 @@ CONFIG_ZONE_DMA32=y
|
||||
CONFIG_ZONE_DEVICE=y
|
||||
# CONFIG_DEVICE_PRIVATE is not set
|
||||
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
|
||||
CONFIG_ARCH_USES_PG_ARCH_X=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_PERCPU_STATS=y
|
||||
# CONFIG_GUP_TEST is not set
|
||||
@@ -1133,6 +1122,7 @@ CONFIG_PCIE_PME=y
|
||||
# CONFIG_PCIE_DPC is not set
|
||||
# CONFIG_PCIE_PTM is not set
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCI_MSI_IRQ_DOMAIN=y
|
||||
CONFIG_PCI_QUIRKS=y
|
||||
CONFIG_PCI_DEBUG=y
|
||||
CONFIG_PCI_STUB=y
|
||||
@@ -1282,6 +1272,7 @@ CONFIG_EFI_RUNTIME_WRAPPERS=y
|
||||
CONFIG_EFI_GENERIC_STUB=y
|
||||
# CONFIG_EFI_ZBOOT is not set
|
||||
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
|
||||
@@ -1335,7 +1326,6 @@ CONFIG_ZRAM_DEF_COMP_LZORLE=y
|
||||
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
||||
# CONFIG_ZRAM_WRITEBACK is not set
|
||||
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
||||
# CONFIG_ZRAM_MULTI_COMP is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
||||
# CONFIG_BLK_DEV_DRBD is not set
|
||||
@@ -1586,7 +1576,6 @@ CONFIG_HW_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_LEGACY_TIOCSTI is not set
|
||||
# CONFIG_LDISC_AUTOLOAD is not set
|
||||
|
||||
#
|
||||
@@ -1662,6 +1651,8 @@ CONFIG_DEVMEM=y
|
||||
CONFIG_DEVPORT=y
|
||||
# CONFIG_TCG_TPM is not set
|
||||
# CONFIG_XILLYBUS is not set
|
||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||
# end of Character devices
|
||||
|
||||
#
|
||||
@@ -1750,7 +1741,6 @@ CONFIG_GPIO_PL061=y
|
||||
# Virtual GPIO drivers
|
||||
#
|
||||
# CONFIG_GPIO_AGGREGATOR is not set
|
||||
# CONFIG_GPIO_LATCH is not set
|
||||
# CONFIG_GPIO_MOCKUP is not set
|
||||
# CONFIG_GPIO_VIRTIO is not set
|
||||
# CONFIG_GPIO_SIM is not set
|
||||
@@ -2168,10 +2158,9 @@ CONFIG_UIO_DMEM_GENIRQ=y
|
||||
# CONFIG_UIO_PRUSS is not set
|
||||
# CONFIG_UIO_MF624 is not set
|
||||
CONFIG_VFIO=y
|
||||
CONFIG_VFIO_CONTAINER=y
|
||||
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||
# CONFIG_VFIO_NOIOMMU is not set
|
||||
CONFIG_VFIO_VIRQFD=y
|
||||
# CONFIG_VFIO_NOIOMMU is not set
|
||||
CONFIG_VFIO_PCI_CORE=y
|
||||
CONFIG_VFIO_PCI_MMAP=y
|
||||
CONFIG_VFIO_PCI_INTX=y
|
||||
@@ -2270,7 +2259,6 @@ CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
|
||||
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
||||
CONFIG_OF_IOMMU=y
|
||||
CONFIG_IOMMU_DMA=y
|
||||
# CONFIG_IOMMUFD is not set
|
||||
# CONFIG_ARM_SMMU is not set
|
||||
# CONFIG_ARM_SMMU_V3 is not set
|
||||
CONFIG_VIRTIO_IOMMU=y
|
||||
@@ -2407,7 +2395,6 @@ CONFIG_ARM_PMU_ACPI=y
|
||||
# CONFIG_HISI_PMU is not set
|
||||
# CONFIG_HISI_PCIE_PMU is not set
|
||||
# CONFIG_HNS3_PMU is not set
|
||||
# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set
|
||||
# end of Performance monitor support
|
||||
|
||||
CONFIG_RAS=y
|
||||
@@ -2583,10 +2570,8 @@ CONFIG_SQUASHFS=y
|
||||
CONFIG_SQUASHFS_FILE_CACHE=y
|
||||
# CONFIG_SQUASHFS_FILE_DIRECT is not set
|
||||
CONFIG_SQUASHFS_DECOMP_SINGLE=y
|
||||
# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
|
||||
CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y
|
||||
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
|
||||
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set
|
||||
# CONFIG_SQUASHFS_DECOMP_MULTI is not set
|
||||
# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
|
||||
# CONFIG_SQUASHFS_XATTR is not set
|
||||
CONFIG_SQUASHFS_ZLIB=y
|
||||
# CONFIG_SQUASHFS_LZ4 is not set
|
||||
@@ -2725,6 +2710,7 @@ CONFIG_CRYPTO_MANAGER2=y
|
||||
# CONFIG_CRYPTO_USER is not set
|
||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
||||
CONFIG_CRYPTO_GF128MUL=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_NULL2=y
|
||||
# CONFIG_CRYPTO_PCRYPT is not set
|
||||
@@ -2886,8 +2872,6 @@ CONFIG_CRYPTO_USER_API_RNG=y
|
||||
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
|
||||
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
|
||||
# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set
|
||||
# CONFIG_CRYPTO_SM4_ARM64_CE_CCM is not set
|
||||
# CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set
|
||||
# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set
|
||||
# end of Accelerated Cryptographic Algorithms for CPU (arm64)
|
||||
|
||||
@@ -2926,7 +2910,6 @@ CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
|
||||
#
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
CONFIG_CRYPTO_LIB_AES=y
|
||||
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
||||
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
||||
@@ -3062,8 +3045,7 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED is not set
|
||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
||||
# CONFIG_DEBUG_INFO_BTF is not set
|
||||
# CONFIG_GDB_SCRIPTS is not set
|
||||
@@ -3224,7 +3206,7 @@ CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
@@ -3263,6 +3245,7 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_TEST_HEXDUMP is not set
|
||||
# CONFIG_STRING_SELFTEST is not set
|
||||
# CONFIG_TEST_STRING_HELPERS is not set
|
||||
# CONFIG_TEST_STRSCPY is not set
|
||||
# CONFIG_TEST_KSTRTOX is not set
|
||||
# CONFIG_TEST_PRINTF is not set
|
||||
# CONFIG_TEST_SCANF is not set
|
||||
@@ -3271,6 +3254,7 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_TEST_XARRAY is not set
|
||||
# CONFIG_TEST_MAPLE_TREE is not set
|
||||
# CONFIG_TEST_RHASHTABLE is not set
|
||||
# CONFIG_TEST_SIPHASH is not set
|
||||
# CONFIG_TEST_IDA is not set
|
||||
# CONFIG_FIND_BIT_BENCHMARK is not set
|
||||
# CONFIG_TEST_FIRMWARE is not set
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/x86 6.2.0 Kernel Configuration
|
||||
# Linux/x86 6.1.6 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
|
||||
CONFIG_CC_VERSION_TEXT="gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4)"
|
||||
CONFIG_CC_IS_GCC=y
|
||||
CONFIG_GCC_VERSION=110300
|
||||
CONFIG_GCC_VERSION=120201
|
||||
CONFIG_CLANG_VERSION=0
|
||||
CONFIG_AS_IS_GNU=y
|
||||
CONFIG_AS_VERSION=23800
|
||||
CONFIG_AS_VERSION=23700
|
||||
CONFIG_LD_IS_BFD=y
|
||||
CONFIG_LD_VERSION=23800
|
||||
CONFIG_LD_VERSION=23700
|
||||
CONFIG_LLD_VERSION=0
|
||||
CONFIG_RUST_IS_AVAILABLE=y
|
||||
CONFIG_CC_CAN_LINK=y
|
||||
CONFIG_CC_CAN_LINK_STATIC=y
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
|
||||
CONFIG_CC_HAS_ASM_INLINE=y
|
||||
@@ -70,6 +70,7 @@ CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_GENERIC_MSI_IRQ=y
|
||||
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_MSI_IOMMU=y
|
||||
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
|
||||
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
|
||||
@@ -227,7 +228,6 @@ CONFIG_INITRAMFS_PRESERVE_MTIME=y
|
||||
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_LD_ORPHAN_WARN=y
|
||||
CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
CONFIG_HAVE_PCSPKR_PLATFORM=y
|
||||
@@ -254,7 +254,6 @@ CONFIG_IO_URING=y
|
||||
CONFIG_ADVISE_SYSCALLS=y
|
||||
CONFIG_MEMBARRIER=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_SELFTEST is not set
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
|
||||
CONFIG_KALLSYMS_BASE_RELATIVE=y
|
||||
@@ -275,6 +274,7 @@ CONFIG_PERF_EVENTS=y
|
||||
# end of Kernel Performance Events And Counters
|
||||
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_RUST is not set
|
||||
# end of General setup
|
||||
|
||||
CONFIG_64BIT=y
|
||||
@@ -294,6 +294,7 @@ CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_ARCH_HAS_CPU_RELAX=y
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
CONFIG_ARCH_NR_GPIO=1024
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
CONFIG_AUDIT_ARCH=y
|
||||
CONFIG_X86_64_SMP=y
|
||||
@@ -421,10 +422,7 @@ CONFIG_X86_INTEL_TSX_MODE_OFF=y
|
||||
# CONFIG_X86_SGX is not set
|
||||
CONFIG_EFI=y
|
||||
CONFIG_EFI_STUB=y
|
||||
# CONFIG_EFI_HANDOVER_PROTOCOL is not set
|
||||
# CONFIG_EFI_MIXED is not set
|
||||
# CONFIG_EFI_FAKE_MEMMAP is not set
|
||||
CONFIG_EFI_RUNTIME_MAP=y
|
||||
# CONFIG_HZ_100 is not set
|
||||
CONFIG_HZ_250=y
|
||||
# CONFIG_HZ_300 is not set
|
||||
@@ -457,20 +455,11 @@ CONFIG_HAVE_LIVEPATCH=y
|
||||
|
||||
CONFIG_CC_HAS_SLS=y
|
||||
CONFIG_CC_HAS_RETURN_THUNK=y
|
||||
CONFIG_CC_HAS_ENTRY_PADDING=y
|
||||
CONFIG_FUNCTION_PADDING_CFI=11
|
||||
CONFIG_FUNCTION_PADDING_BYTES=16
|
||||
CONFIG_CALL_PADDING=y
|
||||
CONFIG_HAVE_CALL_THUNKS=y
|
||||
CONFIG_CALL_THUNKS=y
|
||||
CONFIG_PREFIX_SYMBOLS=y
|
||||
CONFIG_SPECULATION_MITIGATIONS=y
|
||||
CONFIG_PAGE_TABLE_ISOLATION=y
|
||||
CONFIG_RETPOLINE=y
|
||||
CONFIG_RETHUNK=y
|
||||
CONFIG_CPU_UNRET_ENTRY=y
|
||||
CONFIG_CALL_DEPTH_TRACKING=y
|
||||
# CONFIG_CALL_THUNKS_DEBUG is not set
|
||||
CONFIG_CPU_IBPB_ENTRY=y
|
||||
CONFIG_CPU_IBRS_ENTRY=y
|
||||
# CONFIG_SLS is not set
|
||||
@@ -544,7 +533,6 @@ CONFIG_HAVE_ACPI_APEI_NMI=y
|
||||
# CONFIG_ACPI_CONFIGFS is not set
|
||||
# CONFIG_ACPI_PFRUT is not set
|
||||
# CONFIG_ACPI_PCC is not set
|
||||
# CONFIG_ACPI_FFH is not set
|
||||
# CONFIG_PMIC_OPREGION is not set
|
||||
CONFIG_ACPI_VIOT=y
|
||||
# CONFIG_ACPI_PRMT is not set
|
||||
@@ -640,7 +628,6 @@ CONFIG_KVM=y
|
||||
# CONFIG_KVM_WERROR is not set
|
||||
CONFIG_KVM_INTEL=y
|
||||
# CONFIG_KVM_AMD is not set
|
||||
CONFIG_KVM_SMM=y
|
||||
# CONFIG_KVM_XEN is not set
|
||||
CONFIG_AS_AVX512=y
|
||||
CONFIG_AS_SHA1_NI=y
|
||||
@@ -697,7 +684,6 @@ CONFIG_MMU_GATHER_TABLE_FREE=y
|
||||
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
|
||||
CONFIG_MMU_GATHER_MERGE_VMAS=y
|
||||
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
|
||||
CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y
|
||||
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
||||
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
||||
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
||||
@@ -779,9 +765,6 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
|
||||
# end of GCOV-based kernel profiling
|
||||
|
||||
CONFIG_HAVE_GCC_PLUGINS=y
|
||||
CONFIG_FUNCTION_ALIGNMENT_4B=y
|
||||
CONFIG_FUNCTION_ALIGNMENT_16B=y
|
||||
CONFIG_FUNCTION_ALIGNMENT=16
|
||||
# end of General architecture-dependent options
|
||||
|
||||
CONFIG_RT_MUTEXES=y
|
||||
@@ -899,8 +882,7 @@ CONFIG_ZSMALLOC_STAT=y
|
||||
#
|
||||
# CONFIG_SLAB is not set
|
||||
CONFIG_SLUB=y
|
||||
# CONFIG_SLOB_DEPRECATED is not set
|
||||
# CONFIG_SLUB_TINY is not set
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_SLAB_MERGE_DEFAULT=y
|
||||
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
||||
CONFIG_SLAB_FREELIST_HARDENED=y
|
||||
@@ -975,6 +957,7 @@ CONFIG_SECRETMEM=y
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_HAVE_ARCH_USERFAULTFD_WP=y
|
||||
CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y
|
||||
CONFIG_PTE_MARKER=y
|
||||
CONFIG_PTE_MARKER_UFFD_WP=y
|
||||
# CONFIG_LRU_GEN is not set
|
||||
|
||||
@@ -1139,6 +1122,7 @@ CONFIG_PCIE_PME=y
|
||||
# CONFIG_PCIE_DPC is not set
|
||||
# CONFIG_PCIE_PTM is not set
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCI_MSI_IRQ_DOMAIN=y
|
||||
CONFIG_PCI_QUIRKS=y
|
||||
CONFIG_PCI_DEBUG=y
|
||||
CONFIG_PCI_STUB=y
|
||||
@@ -1267,8 +1251,11 @@ CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
|
||||
# EFI (Extensible Firmware Interface) Support
|
||||
#
|
||||
CONFIG_EFI_ESRT=y
|
||||
CONFIG_EFI_RUNTIME_MAP=y
|
||||
# CONFIG_EFI_FAKE_MEMMAP is not set
|
||||
CONFIG_EFI_DXE_MEM_ATTRIBUTES=y
|
||||
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
|
||||
@@ -1309,7 +1296,6 @@ CONFIG_ZRAM_DEF_COMP_LZORLE=y
|
||||
CONFIG_ZRAM_DEF_COMP="lzo-rle"
|
||||
# CONFIG_ZRAM_WRITEBACK is not set
|
||||
# CONFIG_ZRAM_MEMORY_TRACKING is not set
|
||||
# CONFIG_ZRAM_MULTI_COMP is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
|
||||
# CONFIG_BLK_DEV_DRBD is not set
|
||||
@@ -1564,7 +1550,6 @@ CONFIG_HW_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_LEGACY_TIOCSTI is not set
|
||||
# CONFIG_LDISC_AUTOLOAD is not set
|
||||
|
||||
#
|
||||
@@ -1639,6 +1624,8 @@ CONFIG_HANGCHECK_TIMER=y
|
||||
# CONFIG_TCG_TPM is not set
|
||||
# CONFIG_TELCLOCK is not set
|
||||
# CONFIG_XILLYBUS is not set
|
||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||
# end of Character devices
|
||||
|
||||
#
|
||||
@@ -1687,7 +1674,6 @@ CONFIG_GPIOLIB_IRQCHIP=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_CDEV=y
|
||||
CONFIG_GPIO_CDEV_V1=y
|
||||
CONFIG_GPIO_IDIO_16=y
|
||||
|
||||
#
|
||||
# Memory mapped GPIO drivers
|
||||
@@ -1731,7 +1717,6 @@ CONFIG_GPIO_PCI_IDIO_16=y
|
||||
# Virtual GPIO drivers
|
||||
#
|
||||
# CONFIG_GPIO_AGGREGATOR is not set
|
||||
# CONFIG_GPIO_LATCH is not set
|
||||
# CONFIG_GPIO_MOCKUP is not set
|
||||
# CONFIG_GPIO_VIRTIO is not set
|
||||
# CONFIG_GPIO_SIM is not set
|
||||
@@ -1799,7 +1784,6 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0
|
||||
# CONFIG_MAX63XX_WATCHDOG is not set
|
||||
# CONFIG_ACQUIRE_WDT is not set
|
||||
# CONFIG_ADVANTECH_WDT is not set
|
||||
# CONFIG_ADVANTECH_EC_WDT is not set
|
||||
# CONFIG_ALIM1535_WDT is not set
|
||||
# CONFIG_ALIM7101_WDT is not set
|
||||
# CONFIG_EBC_C384_WDT is not set
|
||||
@@ -2140,10 +2124,9 @@ CONFIG_UIO_DMEM_GENIRQ=y
|
||||
# CONFIG_UIO_MF624 is not set
|
||||
# CONFIG_UIO_HV_GENERIC is not set
|
||||
CONFIG_VFIO=y
|
||||
CONFIG_VFIO_CONTAINER=y
|
||||
CONFIG_VFIO_IOMMU_TYPE1=y
|
||||
# CONFIG_VFIO_NOIOMMU is not set
|
||||
CONFIG_VFIO_VIRQFD=y
|
||||
# CONFIG_VFIO_NOIOMMU is not set
|
||||
CONFIG_VFIO_PCI_CORE=y
|
||||
CONFIG_VFIO_PCI_MMAP=y
|
||||
CONFIG_VFIO_PCI_INTX=y
|
||||
@@ -2219,7 +2202,6 @@ CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
|
||||
CONFIG_IOMMU_DMA=y
|
||||
# CONFIG_AMD_IOMMU is not set
|
||||
# CONFIG_INTEL_IOMMU is not set
|
||||
# CONFIG_IOMMUFD is not set
|
||||
# CONFIG_IRQ_REMAP is not set
|
||||
CONFIG_HYPERV_IOMMU=y
|
||||
CONFIG_VIRTIO_IOMMU=y
|
||||
@@ -2562,7 +2544,12 @@ CONFIG_LSM="yama,loadpin,safesetid,integrity"
|
||||
#
|
||||
# Memory initialization
|
||||
#
|
||||
CONFIG_INIT_STACK_NONE=y
|
||||
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
|
||||
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y
|
||||
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
|
||||
# CONFIG_INIT_STACK_NONE is not set
|
||||
# CONFIG_INIT_STACK_ALL_PATTERN is not set
|
||||
CONFIG_INIT_STACK_ALL_ZERO=y
|
||||
# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
|
||||
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
|
||||
CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
|
||||
@@ -2598,6 +2585,7 @@ CONFIG_CRYPTO_MANAGER2=y
|
||||
# CONFIG_CRYPTO_USER is not set
|
||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||
# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set
|
||||
CONFIG_CRYPTO_GF128MUL=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_NULL2=y
|
||||
# CONFIG_CRYPTO_PCRYPT is not set
|
||||
@@ -2807,7 +2795,6 @@ CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
|
||||
#
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
CONFIG_CRYPTO_LIB_AES=y
|
||||
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
# CONFIG_CRYPTO_LIB_CHACHA is not set
|
||||
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
|
||||
@@ -2895,7 +2882,6 @@ CONFIG_FONT_8x16=y
|
||||
CONFIG_SG_POOL=y
|
||||
CONFIG_ARCH_HAS_PMEM_API=y
|
||||
CONFIG_MEMREGION=y
|
||||
CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION=y
|
||||
CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
|
||||
CONFIG_ARCH_HAS_COPY_MC=y
|
||||
CONFIG_ARCH_STACKWALK=y
|
||||
@@ -2936,8 +2922,7 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED is not set
|
||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
||||
# CONFIG_DEBUG_INFO_BTF is not set
|
||||
# CONFIG_GDB_SCRIPTS is not set
|
||||
@@ -3113,7 +3098,6 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
||||
CONFIG_HAVE_FENTRY=y
|
||||
CONFIG_HAVE_OBJTOOL_MCOUNT=y
|
||||
CONFIG_HAVE_OBJTOOL_NOP_MCOUNT=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
|
||||
CONFIG_TRACING_SUPPORT=y
|
||||
@@ -3173,6 +3157,7 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_TEST_HEXDUMP is not set
|
||||
# CONFIG_STRING_SELFTEST is not set
|
||||
# CONFIG_TEST_STRING_HELPERS is not set
|
||||
# CONFIG_TEST_STRSCPY is not set
|
||||
# CONFIG_TEST_KSTRTOX is not set
|
||||
# CONFIG_TEST_PRINTF is not set
|
||||
# CONFIG_TEST_SCANF is not set
|
||||
@@ -3181,6 +3166,7 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_TEST_XARRAY is not set
|
||||
# CONFIG_TEST_MAPLE_TREE is not set
|
||||
# CONFIG_TEST_RHASHTABLE is not set
|
||||
# CONFIG_TEST_SIPHASH is not set
|
||||
# CONFIG_TEST_IDA is not set
|
||||
# CONFIG_FIND_BIT_BENCHMARK is not set
|
||||
# CONFIG_TEST_FIRMWARE is not set
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
CLI_NAME="Cloud Hypervisor"
|
||||
|
||||
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
|
||||
CTR_IMAGE_VERSION="20230316-0"
|
||||
CTR_IMAGE_TAG="cloudhypervisor/dev"
|
||||
CTR_IMAGE_VERSION="20230123-0"
|
||||
CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
|
||||
|
||||
DOCKER_RUNTIME="docker"
|
||||
@@ -172,11 +172,7 @@ process_volumes_args() {
|
||||
cmd_help() {
|
||||
echo ""
|
||||
echo "Cloud Hypervisor $(basename "$0")"
|
||||
echo "Usage: $(basename "$0") [flags] <command> [<command args>]"
|
||||
echo ""
|
||||
echo "Available flags":
|
||||
echo ""
|
||||
echo " --local Set the container image version being used to \"local\"."
|
||||
echo "Usage: $(basename "$0") <command> [<command args>]"
|
||||
echo ""
|
||||
echo "Available commands:"
|
||||
echo ""
|
||||
@@ -539,7 +535,6 @@ cmd_tests() {
|
||||
--volume "$CLH_INTEGRATION_WORKLOADS:$CTR_CLH_INTEGRATION_WORKLOADS" \
|
||||
--env USER="root" \
|
||||
--env CH_LIBC="${libc}" \
|
||||
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \
|
||||
"$CTR_IMAGE" \
|
||||
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
|
||||
fi
|
||||
|
||||
@@ -225,8 +225,8 @@ fi
|
||||
|
||||
BUILD_TARGET="aarch64-unknown-linux-${CH_LIBC}"
|
||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||
export TARGET_CC="musl-gcc"
|
||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||
export TARGET_CC="musl-gcc"
|
||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||
fi
|
||||
|
||||
export RUST_BACKTRACE=1
|
||||
@@ -240,9 +240,7 @@ sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||
|
||||
# Both test_vfio and ovs-dpdk rely on hugepages
|
||||
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||
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`
|
||||
|
||||
@@ -56,8 +56,26 @@ popd
|
||||
|
||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||
|
||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
||||
|
||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||
build_custom_linux
|
||||
SRCDIR=$PWD
|
||||
pushd $WORKLOADS_DIR
|
||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-6.1.6" $LINUX_CUSTOM_DIR
|
||||
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||
pushd $LINUX_CUSTOM_DIR
|
||||
time make bzImage -j `nproc`
|
||||
cp vmlinux $VMLINUX_IMAGE || exit 1
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ -d "$LINUX_CUSTOM_DIR" ]; then
|
||||
rm -rf $LINUX_CUSTOM_DIR
|
||||
fi
|
||||
|
||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||
@@ -71,9 +89,7 @@ fi
|
||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
||||
|
||||
# Test ovs-dpdk relies on hugepages
|
||||
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||
sudo chmod a+rwX /dev/hugepages
|
||||
|
||||
export RUST_BACKTRACE=1
|
||||
|
||||
@@ -45,7 +45,29 @@ if [ $? -ne 0 ]; then
|
||||
fi
|
||||
popd
|
||||
|
||||
build_custom_linux
|
||||
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
|
||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||
|
||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
||||
|
||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||
SRCDIR=$PWD
|
||||
pushd $WORKLOADS_DIR
|
||||
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-6.1.6" $LINUX_CUSTOM_DIR
|
||||
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||
pushd $LINUX_CUSTOM_DIR
|
||||
time make bzImage -j `nproc`
|
||||
cp vmlinux $VMLINUX_IMAGE || exit 1
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ -d "$LINUX_CUSTOM_DIR" ]; then
|
||||
rm -rf $LINUX_CUSTOM_DIR
|
||||
fi
|
||||
|
||||
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||
CFLAGS=""
|
||||
|
||||
@@ -42,8 +42,8 @@ BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||
CFLAGS=""
|
||||
TARGET_CC=""
|
||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||
TARGET_CC="musl-gcc"
|
||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||
TARGET_CC="musl-gcc"
|
||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||
fi
|
||||
|
||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
||||
|
||||
@@ -12,7 +12,9 @@ FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
|
||||
FW="$WORKLOADS_DIR/hypervisor-fw"
|
||||
|
||||
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
|
||||
build_custom_linux
|
||||
if [ ! -f "$VMLINUX_IMAGE" ]; then
|
||||
build_custom_linux
|
||||
fi
|
||||
|
||||
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
|
||||
MNT_DIR="mount_image"
|
||||
@@ -50,9 +52,7 @@ cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
|
||||
cp target/$BUILD_TARGET/release/ch-remote $VFIO_DIR
|
||||
|
||||
# test_vfio rely on hugepages
|
||||
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||
sudo chmod a+rwX /dev/hugepages
|
||||
|
||||
export RUST_BACKTRACE=1
|
||||
|
||||
@@ -24,8 +24,8 @@ BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||
CFLAGS=""
|
||||
TARGET_CC=""
|
||||
if [[ "${BUILD_TARGET}" == "aarch64-unknown-linux-musl" ]]; then
|
||||
export TARGET_CC="musl-gcc"
|
||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||
export TARGET_CC="musl-gcc"
|
||||
export RUSTFLAGS="-C link-arg=-lgcc -C link_arg=-specs -C link_arg=/usr/lib/aarch64-linux-musl/musl-gcc.specs"
|
||||
fi
|
||||
|
||||
# Check if the images are present
|
||||
|
||||
@@ -26,8 +26,8 @@ BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
|
||||
CFLAGS=""
|
||||
TARGET_CC=""
|
||||
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then
|
||||
TARGET_CC="musl-gcc"
|
||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||
TARGET_CC="musl-gcc"
|
||||
CFLAGS="-I /usr/include/x86_64-linux-musl/ -idirafter /usr/include/"
|
||||
fi
|
||||
|
||||
# Check if the images are present
|
||||
|
||||
@@ -169,9 +169,7 @@ sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
|
||||
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
|
||||
|
||||
# Both test_vfio, ovs-dpdk and vDPA tests rely on hugepages
|
||||
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||
sudo chmod a+rwX /dev/hugepages
|
||||
|
||||
# Update max locked memory to 'unlimited' to avoid issues with vDPA
|
||||
|
||||
@@ -95,9 +95,7 @@ fi
|
||||
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
|
||||
|
||||
# setup hugepages
|
||||
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
|
||||
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
|
||||
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
|
||||
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
|
||||
sudo chmod a+rwX /dev/hugepages
|
||||
|
||||
if [ -n "$test_filter" ]; then
|
||||
@@ -107,12 +105,7 @@ fi
|
||||
# Ensure that git commands can be run in this directory (for metrics report)
|
||||
git config --global --add safe.directory $PWD
|
||||
|
||||
RUST_BACKTRACE_VALUE=`echo $RUST_BACKTRACE`
|
||||
if [ -z $RUST_BACKTRACE_VALUE ];then
|
||||
export RUST_BACKTRACE=1
|
||||
else
|
||||
echo "RUST_BACKTRACE is set to: $RUST_BACKTRACE_VALUE"
|
||||
fi
|
||||
export RUST_BACKTRACE=1
|
||||
time target/$BUILD_TARGET/release/performance-metrics ${test_binary_args[*]}
|
||||
RES=$?
|
||||
|
||||
|
||||
@@ -22,4 +22,3 @@ fi
|
||||
|
||||
export RUST_BACKTRACE=1
|
||||
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||
cargo test --doc --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
|
||||
|
||||
@@ -46,7 +46,7 @@ build_custom_linux() {
|
||||
ARCH=$(uname -m)
|
||||
SRCDIR=$PWD
|
||||
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
|
||||
LINUX_CUSTOM_BRANCH="ch-6.2"
|
||||
LINUX_CUSTOM_BRANCH="ch-6.1.6"
|
||||
LINUX_CUSTOM_URL="https://github.com/cloud-hypervisor/linux.git"
|
||||
|
||||
checkout_repo "$LINUX_CUSTOM_DIR" "$LINUX_CUSTOM_URL" "$LINUX_CUSTOM_BRANCH"
|
||||
|
||||
@@ -688,7 +688,7 @@ fn main() {
|
||||
let toplevel: TopLevel = argh::from_env();
|
||||
|
||||
if matches!(toplevel.command, SubCommandEnum::Version(_)) {
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
73
src/main.rs
73
src/main.rs
@@ -8,7 +8,7 @@ extern crate event_monitor;
|
||||
|
||||
use argh::FromArgs;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use log::{warn, LevelFilter};
|
||||
use log::LevelFilter;
|
||||
use option_parser::OptionParser;
|
||||
use seccompiler::SeccompAction;
|
||||
use signal_hook::consts::SIGSYS;
|
||||
@@ -33,8 +33,6 @@ enum Error {
|
||||
#[cfg(feature = "guest_debug")]
|
||||
#[error("Failed to create Debug EventFd: {0}")]
|
||||
CreateDebugEventFd(#[source] std::io::Error),
|
||||
#[error("Failed to create exit EventFd: {0}")]
|
||||
CreateExitEventFd(#[source] std::io::Error),
|
||||
#[error("Failed to open hypervisor interface (is hypervisor interface available?): {0}")]
|
||||
CreateHypervisor(#[source] hypervisor::HypervisorError),
|
||||
#[error("Failed to start the VMM thread: {0}")]
|
||||
@@ -92,9 +90,9 @@ impl log::Log for Logger {
|
||||
let duration = now.duration_since(self.start);
|
||||
|
||||
if record.file().is_some() && record.line().is_some() {
|
||||
write!(
|
||||
writeln!(
|
||||
*(*(self.output.lock().unwrap())),
|
||||
"cloud-hypervisor: {:.6?}: <{}> {}:{}:{} -- {}\r\n",
|
||||
"cloud-hypervisor: {:.6?}: <{}> {}:{}:{} -- {}",
|
||||
duration,
|
||||
std::thread::current().name().unwrap_or("anonymous"),
|
||||
record.level(),
|
||||
@@ -103,9 +101,9 @@ impl log::Log for Logger {
|
||||
record.args()
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
writeln!(
|
||||
*(*(self.output.lock().unwrap())),
|
||||
"cloud-hypervisor: {:.6?}: <{}> {}:{} -- {}\r\n",
|
||||
"cloud-hypervisor: {:.6?}: <{}> {}:{} -- {}",
|
||||
duration,
|
||||
std::thread::current().name().unwrap_or("anonymous"),
|
||||
record.level(),
|
||||
@@ -511,10 +509,8 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
|
||||
|
||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
|
||||
|
||||
let vmm_thread = vmm::start_vmm_thread(
|
||||
vmm::VmmVersionInfo::new(env!("BUILD_VERSION"), env!("CARGO_PKG_VERSION")),
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
&api_socket_path,
|
||||
api_socket_fd,
|
||||
api_evt.try_clone().unwrap(),
|
||||
@@ -526,46 +522,33 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
||||
debug_evt.try_clone().unwrap(),
|
||||
#[cfg(feature = "guest_debug")]
|
||||
vm_debug_evt.try_clone().unwrap(),
|
||||
exit_evt.try_clone().unwrap(),
|
||||
&seccomp_action,
|
||||
hypervisor,
|
||||
)
|
||||
.map_err(Error::StartVmmThread)?;
|
||||
|
||||
let r: Result<(), Error> = (|| {
|
||||
let payload_present = toplevel.kernel.is_some() || toplevel.firmware.is_some();
|
||||
let payload_present = toplevel.kernel.is_some() || toplevel.firmware.is_some();
|
||||
|
||||
if payload_present {
|
||||
let vm_params = toplevel.to_vm_params();
|
||||
let vm_config = config::VmConfig::parse(vm_params).map_err(Error::ParsingConfig)?;
|
||||
if payload_present {
|
||||
let vm_params = toplevel.to_vm_params();
|
||||
let vm_config = config::VmConfig::parse(vm_params).map_err(Error::ParsingConfig)?;
|
||||
|
||||
// Create and boot the VM based off the VM config we just built.
|
||||
let sender = api_request_sender.clone();
|
||||
vmm::api::vm_create(
|
||||
api_evt.try_clone().unwrap(),
|
||||
api_request_sender,
|
||||
Arc::new(Mutex::new(vm_config)),
|
||||
)
|
||||
.map_err(Error::VmCreate)?;
|
||||
vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).map_err(Error::VmBoot)?;
|
||||
} else if let Some(restore_params) = toplevel.restore {
|
||||
vmm::api::vm_restore(
|
||||
api_evt.try_clone().unwrap(),
|
||||
api_request_sender,
|
||||
Arc::new(
|
||||
config::RestoreConfig::parse(&restore_params).map_err(Error::ParsingRestore)?,
|
||||
),
|
||||
)
|
||||
.map_err(Error::VmRestore)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
if r.is_err() {
|
||||
if let Err(e) = exit_evt.write(1) {
|
||||
warn!("writing to exit EventFd: {e}");
|
||||
}
|
||||
// Create and boot the VM based off the VM config we just built.
|
||||
let sender = api_request_sender.clone();
|
||||
vmm::api::vm_create(
|
||||
api_evt.try_clone().unwrap(),
|
||||
api_request_sender,
|
||||
Arc::new(Mutex::new(vm_config)),
|
||||
)
|
||||
.map_err(Error::VmCreate)?;
|
||||
vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).map_err(Error::VmBoot)?;
|
||||
} else if let Some(restore_params) = toplevel.restore {
|
||||
vmm::api::vm_restore(
|
||||
api_evt.try_clone().unwrap(),
|
||||
api_request_sender,
|
||||
Arc::new(config::RestoreConfig::parse(&restore_params).map_err(Error::ParsingRestore)?),
|
||||
)
|
||||
.map_err(Error::VmRestore)?;
|
||||
}
|
||||
|
||||
vmm_thread
|
||||
@@ -573,7 +556,7 @@ fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
|
||||
.map_err(Error::ThreadJoin)?
|
||||
.map_err(Error::VmmThread)?;
|
||||
|
||||
r.map(|_| api_socket_path)
|
||||
Ok(api_socket_path)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -587,7 +570,7 @@ fn main() {
|
||||
let toplevel: TopLevel = argh::from_env();
|
||||
|
||||
if toplevel.version {
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
dirs = "5.0.0"
|
||||
dirs = "4.0.0"
|
||||
epoll = "4.3.1"
|
||||
libc = "0.2.139"
|
||||
once_cell = "1.17.1"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
|
||||
vmm-sys-util = "0.11.0"
|
||||
wait-timeout = "0.2.0"
|
||||
|
||||
@@ -868,6 +868,14 @@ impl Guest {
|
||||
.map_err(Error::Parsing)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn get_initial_apicid(&self) -> Result<u32, Error> {
|
||||
self.ssh_command("grep \"initial apicid\" /proc/cpuinfo | grep -o \"[0-9]*\"")?
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(Error::Parsing)
|
||||
}
|
||||
|
||||
pub fn get_total_memory(&self) -> Result<u32, Error> {
|
||||
self.ssh_command("grep MemTotal /proc/meminfo | grep -o \"[0-9]*\"")?
|
||||
.trim()
|
||||
@@ -1344,7 +1352,6 @@ pub fn parse_iperf3_output(output: &[u8], sender: bool, bandwidth: bool) -> Resu
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum FioOps {
|
||||
Read,
|
||||
RandomRead,
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
extern crate test_infra;
|
||||
|
||||
use api_client::simple_api_command;
|
||||
use api_client::simple_api_full_command;
|
||||
use net_util::MacAddr;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
@@ -32,9 +30,6 @@ use test_infra::*;
|
||||
use vmm_sys_util::{tempdir::TempDir, tempfile::TempFile};
|
||||
use wait_timeout::ChildExt;
|
||||
|
||||
// Constant taken from the VMM crate.
|
||||
const MAX_NUM_PCI_SEGMENTS: u16 = 96;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod x86_64 {
|
||||
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-amd64-custom-20210609-0.raw";
|
||||
@@ -257,6 +252,26 @@ fn prepare_swtpm_daemon(tmp_dir: &TempDir) -> (std::process::Command, String) {
|
||||
(swtpm_command, swtpm_socket_path)
|
||||
}
|
||||
|
||||
fn curl_command(api_socket: &str, method: &str, url: &str, http_body: Option<&str>) {
|
||||
let mut curl_args: Vec<&str> = ["--unix-socket", api_socket, "-i", "-X", method, url].to_vec();
|
||||
|
||||
if let Some(body) = http_body {
|
||||
curl_args.push("-H");
|
||||
curl_args.push("Accept: application/json");
|
||||
curl_args.push("-H");
|
||||
curl_args.push("Content-Type: application/json");
|
||||
curl_args.push("-d");
|
||||
curl_args.push(body);
|
||||
}
|
||||
|
||||
let status = Command::new("curl")
|
||||
.args(curl_args)
|
||||
.status()
|
||||
.expect("Failed to launch curl command");
|
||||
|
||||
assert!(status.success());
|
||||
}
|
||||
|
||||
fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool {
|
||||
let mut cmd = Command::new(clh_command("ch-remote"));
|
||||
cmd.args(["--api-socket", api_socket, command]);
|
||||
@@ -1209,10 +1224,7 @@ fn _test_virtio_fs(
|
||||
.default_net()
|
||||
.args(["--api-socket", &api_socket]);
|
||||
if pci_segment.is_some() {
|
||||
guest_command.args([
|
||||
"--platform",
|
||||
&format!("num_pci_segments={MAX_NUM_PCI_SEGMENTS}"),
|
||||
]);
|
||||
guest_command.args(["--platform", "num_pci_segments=16"]);
|
||||
}
|
||||
|
||||
let fs_params = format!(
|
||||
@@ -1910,7 +1922,7 @@ fn enable_guest_watchdog(guest: &Guest, watchdog_sec: u32) {
|
||||
}
|
||||
|
||||
mod common_parallel {
|
||||
use std::{fs::OpenOptions, io::SeekFrom, os::unix::net::UnixStream};
|
||||
use std::{fs::OpenOptions, io::SeekFrom};
|
||||
|
||||
use crate::*;
|
||||
|
||||
@@ -1948,6 +1960,7 @@ mod common_parallel {
|
||||
guest.wait_vm_boot(Some(120)).unwrap();
|
||||
|
||||
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 1);
|
||||
assert_eq!(guest.get_initial_apicid().unwrap_or(1), 0);
|
||||
assert!(guest.get_total_memory().unwrap_or_default() > 480_000);
|
||||
assert_eq!(guest.get_pci_bridge_class().unwrap_or_default(), "0x060000");
|
||||
|
||||
@@ -2051,16 +2064,19 @@ mod common_parallel {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_cpu_topology_421() {
|
||||
test_cpu_topology(4, 2, 1, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_cpu_topology_142() {
|
||||
test_cpu_topology(1, 4, 2, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_cpu_topology_262() {
|
||||
test_cpu_topology(2, 6, 2, false);
|
||||
}
|
||||
@@ -2232,7 +2248,7 @@ mod common_parallel {
|
||||
"--memory-zone",
|
||||
"id=mem0,size=1G,hotplug_size=2G",
|
||||
"--memory-zone",
|
||||
"id=mem1,size=1G,shared=on",
|
||||
"id=mem1,size=1G,file=/dev/shm",
|
||||
"--memory-zone",
|
||||
"id=mem2,size=1G,host_numa_node=0,hotplug_size=2G",
|
||||
])
|
||||
@@ -2321,10 +2337,7 @@ mod common_parallel {
|
||||
.args(["--memory", "size=512M"])
|
||||
.args(["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
||||
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||
.args([
|
||||
"--platform",
|
||||
&format!("num_pci_segments={MAX_NUM_PCI_SEGMENTS},iommu_segments=[1]"),
|
||||
])
|
||||
.args(["--platform", "num_pci_segments=16,iommu_segments=[1]"])
|
||||
.default_disks()
|
||||
.capture_output()
|
||||
.default_net();
|
||||
@@ -2480,10 +2493,7 @@ mod common_parallel {
|
||||
.args(["--memory", "size=512M"])
|
||||
.args(["--kernel", direct_kernel_boot_path().to_str().unwrap()])
|
||||
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||
.args([
|
||||
"--platform",
|
||||
&format!("num_pci_segments={MAX_NUM_PCI_SEGMENTS}"),
|
||||
])
|
||||
.args(["--platform", "num_pci_segments=16"])
|
||||
.args([
|
||||
"--disk",
|
||||
format!(
|
||||
@@ -2510,15 +2520,15 @@ mod common_parallel {
|
||||
let grep_cmd = "lspci | grep \"Host bridge\" | wc -l";
|
||||
|
||||
let r = std::panic::catch_unwind(|| {
|
||||
// There should be MAX_NUM_PCI_SEGMENTS PCI host bridges in the guest.
|
||||
// There should be 16 PCI host bridges in the guest.
|
||||
assert_eq!(
|
||||
guest
|
||||
.ssh_command(grep_cmd)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.parse::<u16>()
|
||||
.parse::<u32>()
|
||||
.unwrap_or_default(),
|
||||
MAX_NUM_PCI_SEGMENTS
|
||||
16
|
||||
);
|
||||
|
||||
// Check both if /dev/vdc exists and if the block size is 4M.
|
||||
@@ -3734,7 +3744,7 @@ mod common_parallel {
|
||||
// line (We tag the command line from cloud-hypervisor for that purpose).
|
||||
// The third device is added to validate that hotplug works correctly since
|
||||
// it is being added to the L2 VM through hotplugging mechanism.
|
||||
// Also, we pass-through a virtio-blk device to the L2 VM to test the 32-bit
|
||||
// Also, we pass-through a vitio-blk device to the L2 VM to test the 32-bit
|
||||
// vfio device support
|
||||
fn test_vfio() {
|
||||
setup_vfio_network_interfaces();
|
||||
@@ -4054,9 +4064,8 @@ mod common_parallel {
|
||||
|
||||
thread::sleep(std::time::Duration::new(1, 0));
|
||||
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
// Verify API server is running
|
||||
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
|
||||
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
|
||||
|
||||
// Create the VM first
|
||||
let cpu_count: u8 = 4;
|
||||
@@ -4109,9 +4118,8 @@ mod common_parallel {
|
||||
|
||||
thread::sleep(std::time::Duration::new(1, 0));
|
||||
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
// Verify API server is running
|
||||
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
|
||||
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
|
||||
|
||||
// Create the VM first
|
||||
let cpu_count: u8 = 4;
|
||||
@@ -4122,12 +4130,15 @@ mod common_parallel {
|
||||
);
|
||||
|
||||
let r = std::panic::catch_unwind(|| {
|
||||
// socket has to be created again inside catch_unwind block to avoid errors
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.create",
|
||||
Some(&http_body),
|
||||
);
|
||||
|
||||
// Then boot it
|
||||
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
|
||||
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
|
||||
|
||||
guest.wait_vm_boot(None).unwrap();
|
||||
|
||||
@@ -4144,10 +4155,15 @@ mod common_parallel {
|
||||
thread::sleep(std::time::Duration::new(20, 0));
|
||||
|
||||
// Then shut it down
|
||||
simple_api_command(&mut socket, "PUT", "shutdown", None).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.shutdown",
|
||||
None,
|
||||
);
|
||||
|
||||
// Then boot it again
|
||||
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
|
||||
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
|
||||
|
||||
guest.wait_vm_boot(None).unwrap();
|
||||
|
||||
@@ -4180,9 +4196,8 @@ mod common_parallel {
|
||||
|
||||
thread::sleep(std::time::Duration::new(1, 0));
|
||||
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
// Verify API server is running
|
||||
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
|
||||
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
|
||||
|
||||
// Create the VM first
|
||||
let cpu_count: u8 = 4;
|
||||
@@ -4193,12 +4208,15 @@ mod common_parallel {
|
||||
);
|
||||
|
||||
let r = std::panic::catch_unwind(|| {
|
||||
// socket has to be created again inside catch_unwind block to avoid errors
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.create",
|
||||
Some(&http_body),
|
||||
);
|
||||
|
||||
// Then boot it
|
||||
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
|
||||
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
|
||||
|
||||
guest.wait_vm_boot(None).unwrap();
|
||||
|
||||
@@ -4215,12 +4233,22 @@ mod common_parallel {
|
||||
thread::sleep(std::time::Duration::new(20, 0));
|
||||
|
||||
// Then delete it
|
||||
simple_api_command(&mut socket, "PUT", "delete", None).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.delete",
|
||||
None,
|
||||
);
|
||||
|
||||
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.create",
|
||||
Some(&http_body),
|
||||
);
|
||||
|
||||
// Then boot it again
|
||||
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
|
||||
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
|
||||
|
||||
guest.wait_vm_boot(None).unwrap();
|
||||
|
||||
@@ -4254,9 +4282,8 @@ mod common_parallel {
|
||||
|
||||
thread::sleep(std::time::Duration::new(1, 0));
|
||||
|
||||
let mut socket = UnixStream::connect(&api_socket).unwrap();
|
||||
// Verify API server is running
|
||||
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
|
||||
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
|
||||
|
||||
// Create the VM first
|
||||
let cpu_count: u8 = 4;
|
||||
@@ -4265,12 +4292,15 @@ mod common_parallel {
|
||||
direct_kernel_boot_path().to_str().unwrap(),
|
||||
DIRECT_KERNEL_BOOT_CMDLINE,
|
||||
);
|
||||
|
||||
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
|
||||
curl_command(
|
||||
&api_socket,
|
||||
"PUT",
|
||||
"http://localhost/api/v1/vm.create",
|
||||
Some(&http_body),
|
||||
);
|
||||
|
||||
// Then boot it
|
||||
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
|
||||
|
||||
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
|
||||
thread::sleep(std::time::Duration::new(20, 0));
|
||||
|
||||
let r = std::panic::catch_unwind(|| {
|
||||
@@ -5207,7 +5237,6 @@ mod common_parallel {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_virtio_balloon_free_page_reporting() {
|
||||
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
|
||||
let guest = Guest::new(Box::new(focal));
|
||||
@@ -5307,10 +5336,7 @@ mod common_parallel {
|
||||
.capture_output();
|
||||
|
||||
if pci_segment.is_some() {
|
||||
cmd.args([
|
||||
"--platform",
|
||||
&format!("num_pci_segments={MAX_NUM_PCI_SEGMENTS}"),
|
||||
]);
|
||||
cmd.args(["--platform", "num_pci_segments=16"]);
|
||||
}
|
||||
|
||||
let mut child = cmd.spawn().unwrap();
|
||||
@@ -5446,10 +5472,7 @@ mod common_parallel {
|
||||
.capture_output();
|
||||
|
||||
if pci_segment.is_some() {
|
||||
cmd.args([
|
||||
"--platform",
|
||||
&format!("num_pci_segments={MAX_NUM_PCI_SEGMENTS}"),
|
||||
]);
|
||||
cmd.args(["--platform", "num_pci_segments=16"]);
|
||||
}
|
||||
|
||||
let mut child = cmd.spawn().unwrap();
|
||||
@@ -6277,13 +6300,11 @@ mod common_parallel {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_arch = "aarch64", ignore = "See #5443")]
|
||||
fn test_macvtap() {
|
||||
_test_macvtap(false, "guestmacvtap0", "hostmacvtap0")
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_arch = "aarch64", ignore = "See #5443")]
|
||||
fn test_macvtap_hotplug() {
|
||||
_test_macvtap(true, "guestmacvtap1", "hostmacvtap1")
|
||||
}
|
||||
|
||||
@@ -309,7 +309,11 @@ impl Emulator {
|
||||
}
|
||||
|
||||
self.established_flag_cached = true;
|
||||
self.established_flag = est.resp.bit == 0;
|
||||
if est.resp.bit != 0 {
|
||||
self.established_flag = false;
|
||||
} else {
|
||||
self.established_flag = true;
|
||||
}
|
||||
|
||||
self.established_flag
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ edition = "2021"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
once_cell = "1.17.1"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
|
||||
[features]
|
||||
tracing = []
|
||||
|
||||
@@ -11,5 +11,5 @@ crc32c = "0.6.3"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
remain = "0.2.6"
|
||||
thiserror = "1.0.39"
|
||||
thiserror = "1.0.38"
|
||||
uuid = { version = "1.3.0", features = ["v4"] }
|
||||
|
||||
@@ -145,7 +145,11 @@ impl DiskSpec {
|
||||
let bits = f
|
||||
.read_u32::<LittleEndian>()
|
||||
.map_err(VhdxMetadataError::ReadMetadata)?;
|
||||
disk_spec.has_parent = bits & BLOCK_HAS_PARENT != 0;
|
||||
if bits & BLOCK_HAS_PARENT != 0 {
|
||||
disk_spec.has_parent = true;
|
||||
} else {
|
||||
disk_spec.has_parent = false;
|
||||
}
|
||||
|
||||
metadata_presence |= METADATA_FILE_PARAMETER_PRESENT;
|
||||
} else if metadata_entry.item_id
|
||||
|
||||
@@ -17,7 +17,7 @@ qcow = { path = "../qcow" }
|
||||
vhost = { version = "0.6.0", features = ["vhost-user-slave"] }
|
||||
vhost-user-backend = "0.8.0"
|
||||
virtio-bindings = "0.2.0"
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-memory = "0.10.0"
|
||||
vmm-sys-util = "0.11.0"
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ fn main() {
|
||||
let toplevel: TopLevel = argh::from_env();
|
||||
|
||||
if toplevel.version {
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ fn main() {
|
||||
let toplevel: TopLevel = argh::from_env();
|
||||
|
||||
if toplevel.version {
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILD_VERSION"));
|
||||
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ edition = "2021"
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
arc-swap = "1.5.1"
|
||||
block_util = { path = "../block_util" }
|
||||
byteorder = "1.4.3"
|
||||
epoll = "4.3.1"
|
||||
event_monitor = { path = "../event_monitor" }
|
||||
io-uring = "0.5.13"
|
||||
io-uring = "0.5.12"
|
||||
libc = "0.2.139"
|
||||
log = "0.4.17"
|
||||
net_gen = { path = "../net_gen" }
|
||||
@@ -22,15 +22,15 @@ net_util = { path = "../net_util" }
|
||||
pci = { path = "../pci" }
|
||||
rate_limiter = { path = "../rate_limiter" }
|
||||
seccompiler = "0.3.0"
|
||||
serde = { version = "1.0.156", features = ["derive"] }
|
||||
serde_json = "1.0.96"
|
||||
serde = { version = "1.0.151", features = ["derive"] }
|
||||
serde_json = "1.0.93"
|
||||
serial_buffer = { path = "../serial_buffer" }
|
||||
thiserror = "1.0.39"
|
||||
versionize = "0.1.10"
|
||||
thiserror = "1.0.38"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vhost = { version = "0.6.0", features = ["vhost-user-master", "vhost-user-slave", "vhost-kern", "vhost-vdpa"] }
|
||||
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
||||
@@ -39,24 +39,19 @@ pub mod vhost_user;
|
||||
pub mod vsock;
|
||||
pub mod watchdog;
|
||||
|
||||
pub use self::balloon::Balloon;
|
||||
pub use self::block::{Block, BlockState};
|
||||
pub use self::console::{Console, ConsoleResizer, Endpoint};
|
||||
pub use self::device::{
|
||||
DmaRemapping, UserspaceMapping, VirtioCommon, VirtioDevice, VirtioInterrupt,
|
||||
VirtioInterruptType, VirtioSharedMemoryList,
|
||||
};
|
||||
pub use self::epoll_helper::{
|
||||
EpollHelper, EpollHelperError, EpollHelperHandler, EPOLL_HELPER_EVENT_LAST,
|
||||
};
|
||||
pub use self::iommu::{AccessPlatformMapping, Iommu, IommuMapping};
|
||||
pub use self::mem::{BlocksState, Mem, VirtioMemMappingSource, VIRTIO_MEM_ALIGN_SIZE};
|
||||
pub use self::net::{Net, NetCtrlEpollHandler};
|
||||
pub use self::pmem::Pmem;
|
||||
pub use self::rng::Rng;
|
||||
pub use self::vdpa::{Vdpa, VdpaDmaMapping};
|
||||
pub use self::vsock::Vsock;
|
||||
pub use self::watchdog::Watchdog;
|
||||
pub use self::balloon::*;
|
||||
pub use self::block::*;
|
||||
pub use self::console::*;
|
||||
pub use self::device::*;
|
||||
pub use self::epoll_helper::*;
|
||||
pub use self::iommu::*;
|
||||
pub use self::mem::*;
|
||||
pub use self::net::*;
|
||||
pub use self::pmem::*;
|
||||
pub use self::rng::*;
|
||||
pub use self::vdpa::*;
|
||||
pub use self::vsock::*;
|
||||
pub use self::watchdog::*;
|
||||
use vm_memory::{bitmap::AtomicBitmap, GuestAddress, GuestMemory};
|
||||
use vm_virtio::VirtioDeviceType;
|
||||
|
||||
@@ -91,8 +86,8 @@ pub enum ActivateError {
|
||||
ThreadSpawn(std::io::Error),
|
||||
#[error("Failed to setup vhost-user-fs daemon: {0}")]
|
||||
VhostUserFsSetup(vhost_user::Error),
|
||||
#[error("Failed to setup vhost-user daemon: {0}")]
|
||||
VhostUserSetup(vhost_user::Error),
|
||||
#[error("Failed to setup vhost-user-blk daemon: {0}")]
|
||||
VhostUserBlkSetup(vhost_user::Error),
|
||||
#[error("Failed to create seccomp filter: {0}")]
|
||||
CreateSeccompFilter(seccompiler::Error),
|
||||
#[error("Failed to create rate limiter: {0}")]
|
||||
|
||||
@@ -259,7 +259,6 @@ fn virtio_thread_common() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
(libc::SYS_madvise, vec![]),
|
||||
(libc::SYS_mmap, vec![]),
|
||||
(libc::SYS_mprotect, vec![]),
|
||||
(libc::SYS_mremap, vec![]),
|
||||
(libc::SYS_munmap, vec![]),
|
||||
(libc::SYS_openat, vec![]),
|
||||
(libc::SYS_read, vec![]),
|
||||
|
||||
@@ -605,7 +605,7 @@ impl VirtioDevice for Fs {
|
||||
&mut self,
|
||||
shm_regions: VirtioSharedMemoryList,
|
||||
) -> std::result::Result<(), crate::Error> {
|
||||
if let Some(cache) = self.cache.as_mut() {
|
||||
if let Some(mut cache) = self.cache.as_mut() {
|
||||
cache.0 = shm_regions;
|
||||
Ok(())
|
||||
} else {
|
||||
|
||||
@@ -237,7 +237,7 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
||||
.map_err(|e| {
|
||||
EpollHelperError::IoError(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("failed reconnecting vhost-user backend: {e:?}"),
|
||||
format!("failed reconnecting vhost-user backend{e:?}"),
|
||||
))
|
||||
})?;
|
||||
|
||||
@@ -340,7 +340,7 @@ impl VhostUserCommon {
|
||||
&slave_req_handler,
|
||||
inflight.as_mut(),
|
||||
)
|
||||
.map_err(ActivateError::VhostUserSetup)?;
|
||||
.map_err(ActivateError::VhostUserBlkSetup)?;
|
||||
|
||||
Ok(VhostUserEpollHandler {
|
||||
vu: vu.clone(),
|
||||
@@ -413,7 +413,7 @@ impl VhostUserCommon {
|
||||
pub fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
if let Some(vu) = &self.vu {
|
||||
vu.lock().unwrap().pause_vhost_user().map_err(|e| {
|
||||
MigratableError::Pause(anyhow!("Error pausing vhost-user backend: {:?}", e))
|
||||
MigratableError::Pause(anyhow!("Error pausing vhost-user-blk backend: {:?}", e))
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -423,7 +423,7 @@ impl VhostUserCommon {
|
||||
pub fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||
if let Some(vu) = &self.vu {
|
||||
vu.lock().unwrap().resume_vhost_user().map_err(|e| {
|
||||
MigratableError::Resume(anyhow!("Error resuming vhost-user backend: {:?}", e))
|
||||
MigratableError::Resume(anyhow!("Error resuming vhost-user-blk backend: {:?}", e))
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//! The main job of `VsockConnection` is to forward data traffic, back and forth, between a
|
||||
//! guest-side AF_VSOCK socket and a host-side generic `Read + Write + AsRawFd` stream, while
|
||||
//! also managing its internal state.
|
||||
//! To that end, `VsockConnection` implements:
|
||||
//! - `VsockChannel` for:
|
||||
//! - moving data from the host stream to a guest-provided RX buffer, via `recv_pkt()`; and
|
||||
//! - moving data from a guest-provided TX buffer to the host stream, via `send_pkt()`; and
|
||||
//! - updating its internal state, by absorbing control packets (anything other than
|
||||
//! VSOCK_OP_RW).
|
||||
//! - `VsockEpollListener` for getting notified about the availability of data or free buffer
|
||||
//! space at the host stream.
|
||||
//!
|
||||
//! Note: there is a certain asymmetry to the RX and TX data flows:
|
||||
//! - RX transfers do not need any data buffering, since data is read straight from the
|
||||
//! host stream and into the guest-provided RX buffer;
|
||||
//! - TX transfers may require some data to be buffered by `VsockConnection`, if the host
|
||||
//! peer can't keep up with reading the data that we're writing. This is because, once
|
||||
//! the guest driver provides some data in a virtio TX buffer, the vsock device must
|
||||
//! consume it. If that data can't be forwarded straight to the host stream, we'll
|
||||
//! have to store it in a buffer (and flush it at a later time). Vsock flow control
|
||||
//! ensures that our TX buffer doesn't overflow.
|
||||
//
|
||||
/// The main job of `VsockConnection` is to forward data traffic, back and forth, between a
|
||||
/// guest-side AF_VSOCK socket and a host-side generic `Read + Write + AsRawFd` stream, while
|
||||
/// also managing its internal state.
|
||||
/// To that end, `VsockConnection` implements:
|
||||
/// - `VsockChannel` for:
|
||||
/// - moving data from the host stream to a guest-provided RX buffer, via `recv_pkt()`; and
|
||||
/// - moving data from a guest-provided TX buffer to the host stream, via `send_pkt()`; and
|
||||
/// - updating its internal state, by absorbing control packets (anything other than
|
||||
/// VSOCK_OP_RW).
|
||||
/// - `VsockEpollListener` for getting notified about the availability of data or free buffer
|
||||
/// space at the host stream.
|
||||
///
|
||||
/// Note: there is a certain asymmetry to the RX and TX data flows:
|
||||
/// - RX transfers do not need any data buffering, since data is read straight from the
|
||||
/// host stream and into the guest-provided RX buffer;
|
||||
/// - TX transfers may require some data to be buffered by `VsockConnection`, if the host
|
||||
/// peer can't keep up with reading the data that we're writing. This is because, once
|
||||
/// the guest driver provides some data in a virtio TX buffer, the vsock device must
|
||||
/// consume it. If that data can't be forwarded straight to the host stream, we'll
|
||||
/// have to store it in a buffer (and flush it at a later time). Vsock flow control
|
||||
/// ensures that our TX buffer doesn't overflow.
|
||||
///
|
||||
// The code in this file is best read with a fresh memory of the vsock protocol inner-workings.
|
||||
// To help with that, here is a
|
||||
//
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//! This module implements our vsock connection state machine. The heavy lifting is done by
|
||||
//! `connection::VsockConnection`, while this file only defines some constants and helper structs.
|
||||
|
||||
/// This module implements our vsock connection state machine. The heavy lifting is done by
|
||||
/// `connection::VsockConnection`, while this file only defines some constants and helper structs.
|
||||
///
|
||||
mod connection;
|
||||
mod txbuf;
|
||||
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! `VsockPacket` provides a thin wrapper over the buffers exchanged via virtio queues.
|
||||
//! There are two components to a vsock packet, each using its own descriptor in a
|
||||
//! virtio queue:
|
||||
//! - the packet header; and
|
||||
//! - the packet data/buffer.
|
||||
//! There is a 1:1 relation between descriptor chains and packets: the first (chain head) holds
|
||||
//! the header, and an optional second descriptor holds the data. The second descriptor is only
|
||||
//! present for data packets (VSOCK_OP_RW).
|
||||
//!
|
||||
//! `VsockPacket` wraps these two buffers and provides direct access to the data stored
|
||||
//! in guest memory. This is done to avoid unnecessarily copying data from guest memory
|
||||
//! to temporary buffers, before passing it on to the vsock backend.
|
||||
|
||||
/// `VsockPacket` provides a thin wrapper over the buffers exchanged via virtio queues.
|
||||
/// There are two components to a vsock packet, each using its own descriptor in a
|
||||
/// virtio queue:
|
||||
/// - the packet header; and
|
||||
/// - the packet data/buffer.
|
||||
/// There is a 1:1 relation between descriptor chains and packets: the first (chain head) holds
|
||||
/// the header, and an optional second descriptor holds the data. The second descriptor is only
|
||||
/// present for data packets (VSOCK_OP_RW).
|
||||
///
|
||||
/// `VsockPacket` wraps these two buffers and provides direct access to the data stored
|
||||
/// in guest memory. This is done to avoid unnecessarily copying data from guest memory
|
||||
/// to temporary buffers, before passing it on to the vsock backend.
|
||||
///
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
@@ -436,6 +436,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn test_tx_packet_assembly() {
|
||||
// Test case: successful TX packet assembly.
|
||||
{
|
||||
@@ -580,6 +581,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn test_packet_hdr_accessors() {
|
||||
const SRC_CID: u64 = 1;
|
||||
const DST_CID: u64 = 2;
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! This module implements the Unix Domain Sockets backend for vsock - a mediator between
|
||||
//! guest-side AF_VSOCK sockets and host-side AF_UNIX sockets. The heavy lifting is performed by
|
||||
//! `muxer::VsockMuxer`, a connection multiplexer that uses `super::csm::VsockConnection` for
|
||||
//! handling vsock connection states.
|
||||
//!
|
||||
//! Check out `muxer.rs` for a more detailed explanation of the inner workings of this backend.
|
||||
|
||||
/// This module implements the Unix Domain Sockets backend for vsock - a mediator between
|
||||
/// guest-side AF_VSOCK sockets and host-side AF_UNIX sockets. The heavy lifting is performed by
|
||||
/// `muxer::VsockMuxer`, a connection multiplexer that uses `super::csm::VsockConnection` for
|
||||
/// handling vsock connection states.
|
||||
/// Check out `muxer.rs` for a more detailed explanation of the inner workings of this backend.
|
||||
///
|
||||
mod muxer;
|
||||
mod muxer_killq;
|
||||
mod muxer_rxq;
|
||||
|
||||
@@ -2,42 +2,35 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! `VsockMuxer` is the device-facing component of the Unix domain sockets vsock backend. I.e.
|
||||
//! by implementing the `VsockBackend` trait, it abstracts away the gory details of translating
|
||||
//! between AF_VSOCK and AF_UNIX, and presents a clean interface to the rest of the vsock
|
||||
//! device model.
|
||||
//!
|
||||
//! The vsock muxer has two main roles:
|
||||
//!
|
||||
//! ## Vsock connection multiplexer
|
||||
//!
|
||||
//! It's the muxer's job to create, manage, and terminate `VsockConnection` objects. The
|
||||
//! muxer also routes packets to their owning connections. It does so via a connection
|
||||
//! `HashMap`, keyed by what is basically a (host_port, guest_port) tuple.
|
||||
//!
|
||||
//! Vsock packet traffic needs to be inspected, in order to detect connection request
|
||||
//! packets (leading to the creation of a new connection), and connection reset packets
|
||||
//! (leading to the termination of an existing connection). All other packets, though, must
|
||||
//! belong to an existing connection and, as such, the muxer simply forwards them.
|
||||
//!
|
||||
//! ## Event dispatcher
|
||||
//!
|
||||
//! There are three event categories that the vsock backend is interested it:
|
||||
//! 1. A new host-initiated connection is ready to be accepted from the listening host Unix
|
||||
//! socket;
|
||||
//! 2. Data is available for reading from a newly-accepted host-initiated connection (i.e.
|
||||
//! the host is ready to issue a vsock connection request, informing us of the
|
||||
//! destination port to which it wants to connect);
|
||||
//! 3. Some event was triggered for a connected Unix socket, that belongs to a
|
||||
//! `VsockConnection`.
|
||||
//!
|
||||
//! The muxer gets notified about all of these events, because, as a `VsockEpollListener`
|
||||
//! implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All
|
||||
//! other pollable FDs are then registered under this nested epoll FD.
|
||||
//!
|
||||
//! To route all these events to their handlers, the muxer uses another `HashMap` object,
|
||||
//! mapping `RawFd`s to `EpollListener`s.
|
||||
|
||||
/// `VsockMuxer` is the device-facing component of the Unix domain sockets vsock backend. I.e.
|
||||
/// by implementing the `VsockBackend` trait, it abstracts away the gory details of translating
|
||||
/// between AF_VSOCK and AF_UNIX, and presents a clean interface to the rest of the vsock
|
||||
/// device model.
|
||||
///
|
||||
/// The vsock muxer has two main roles:
|
||||
/// 1. Vsock connection multiplexer:
|
||||
/// It's the muxer's job to create, manage, and terminate `VsockConnection` objects. The
|
||||
/// muxer also routes packets to their owning connections. It does so via a connection
|
||||
/// `HashMap`, keyed by what is basically a (host_port, guest_port) tuple.
|
||||
/// Vsock packet traffic needs to be inspected, in order to detect connection request
|
||||
/// packets (leading to the creation of a new connection), and connection reset packets
|
||||
/// (leading to the termination of an existing connection). All other packets, though, must
|
||||
/// belong to an existing connection and, as such, the muxer simply forwards them.
|
||||
/// 2. Event dispatcher
|
||||
/// There are three event categories that the vsock backend is interested it:
|
||||
/// 1. A new host-initiated connection is ready to be accepted from the listening host Unix
|
||||
/// socket;
|
||||
/// 2. Data is available for reading from a newly-accepted host-initiated connection (i.e.
|
||||
/// the host is ready to issue a vsock connection request, informing us of the
|
||||
/// destination port to which it wants to connect);
|
||||
/// 3. Some event was triggered for a connected Unix socket, that belongs to a
|
||||
/// `VsockConnection`.
|
||||
/// The muxer gets notified about all of these events, because, as a `VsockEpollListener`
|
||||
/// implementor, it gets to register a nested epoll FD into the main VMM epolling loop. All
|
||||
/// other pollable FDs are then registered under this nested epoll FD.
|
||||
/// To route all these events to their handlers, the muxer uses another `HashMap` object,
|
||||
/// mapping `RawFd`s to `EpollListener`s.
|
||||
///
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
@@ -87,7 +80,7 @@ enum EpollListener {
|
||||
},
|
||||
/// A listener interested in new host-initiated connections.
|
||||
HostSock,
|
||||
/// A listener interested in reading host "connect \<port>" commands from a freshly
|
||||
/// A listener interested in reading host "connect <port>" commands from a freshly
|
||||
/// connected host socket.
|
||||
LocalStream(UnixStream),
|
||||
}
|
||||
@@ -113,7 +106,7 @@ pub struct VsockMuxer {
|
||||
/// The Unix socket, through which host-initiated connections are accepted.
|
||||
host_sock: UnixListener,
|
||||
/// The file system path of the host-side Unix socket. This is used to figure out the path
|
||||
/// to Unix sockets listening on specific ports. I.e. "\<this path>_\<port number>".
|
||||
/// to Unix sockets listening on specific ports. I.e. "<this path>_<port number>".
|
||||
host_sock_path: String,
|
||||
/// The nested epoll File, used to register epoll listeners.
|
||||
epoll_file: File,
|
||||
|
||||
@@ -2,29 +2,29 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! `MuxerKillQ` implements a helper object that `VsockMuxer` can use for scheduling forced
|
||||
//! connection termination. I.e. after one peer issues a clean shutdown request
|
||||
//! (VSOCK_OP_SHUTDOWN), the concerned connection is queued for termination (VSOCK_OP_RST) in
|
||||
//! the near future (herein implemented via an expiring timer).
|
||||
//!
|
||||
//! Whenever the muxer needs to schedule a connection for termination, it pushes it (or rather
|
||||
//! an identifier - the connection key) to this queue. A subsequent pop() operation will
|
||||
//! succeed if and only if the first connection in the queue is ready to be terminated (i.e.
|
||||
//! its kill timer expired).
|
||||
//!
|
||||
//! Without using this queue, the muxer would have to walk its entire connection pool
|
||||
//! (hashmap), whenever it needs to check for expired kill timers. With this queue, both
|
||||
//! scheduling and termination are performed in constant time. However, since we don't want to
|
||||
//! waste space on a kill queue that's as big as the connection hashmap itself, it is possible
|
||||
//! that this queue may become full at times. We call this kill queue "synchronized" if we are
|
||||
//! certain that all connections that are awaiting termination are present in the queue. This
|
||||
//! means a simple constant-time pop() operation is enough to check whether any connections
|
||||
//! need to be terminated. When the kill queue becomes full, though, pushing fails, so
|
||||
//! connections that should be terminated are left out. The queue is not synchronized anymore.
|
||||
//! When that happens, the muxer will first drain the queue, and then replace it with a new
|
||||
//! queue, created by walking the connection pool, looking for connections that will be
|
||||
//! expiring in the future.
|
||||
|
||||
/// `MuxerKillQ` implements a helper object that `VsockMuxer` can use for scheduling forced
|
||||
/// connection termination. I.e. after one peer issues a clean shutdown request
|
||||
/// (VSOCK_OP_SHUTDOWN), the concerned connection is queued for termination (VSOCK_OP_RST) in
|
||||
/// the near future (herein implemented via an expiring timer).
|
||||
///
|
||||
/// Whenever the muxer needs to schedule a connection for termination, it pushes it (or rather
|
||||
/// an identifier - the connection key) to this queue. A subsequent pop() operation will
|
||||
/// succeed if and only if the first connection in the queue is ready to be terminated (i.e.
|
||||
/// its kill timer expired).
|
||||
///
|
||||
/// Without using this queue, the muxer would have to walk its entire connection pool
|
||||
/// (hashmap), whenever it needs to check for expired kill timers. With this queue, both
|
||||
/// scheduling and termination are performed in constant time. However, since we don't want to
|
||||
/// waste space on a kill queue that's as big as the connection hashmap itself, it is possible
|
||||
/// that this queue may become full at times. We call this kill queue "synchronized" if we are
|
||||
/// certain that all connections that are awaiting termination are present in the queue. This
|
||||
/// means a simple constant-time pop() operation is enough to check whether any connections
|
||||
/// need to be terminated. When the kill queue becomes full, though, pushing fails, so
|
||||
/// connections that should be terminated are left out. The queue is not synchronized anymore.
|
||||
/// When that happens, the muxer will first drain the queue, and then replace it with a new
|
||||
/// queue, created by walking the connection pool, looking for connections that will be
|
||||
/// expiring in the future.
|
||||
///
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::time::Instant;
|
||||
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! `MuxerRxQ` implements a helper object that `VsockMuxer` can use for queuing RX (host -> guest)
|
||||
//! packets (or rather instructions on how to build said packets).
|
||||
//!
|
||||
//! Under ideal operation, every connection, that has pending RX data, will be present in the muxer
|
||||
//! RX queue. However, since the RX queue is smaller than the connection pool, it may, under some
|
||||
//! conditions, become full, meaning that it can no longer account for all the connections that can
|
||||
//! yield RX data. When that happens, we say that it is no longer "synchronized" (i.e. with the
|
||||
//! connection pool). A desynchronized RX queue still holds valid data, and the muxer will
|
||||
//! continue to pop packets from it. However, when a desynchronized queue is drained, additional
|
||||
//! data may still be available, so the muxer will have to perform a more costly walk of the entire
|
||||
//! connection pool to find it. This walk is performed here, as part of building an RX queue from
|
||||
//! the connection pool. When an out-of-sync is drained, the muxer will discard it, and attempt to
|
||||
//! rebuild a synced one.
|
||||
|
||||
/// `MuxerRxQ` implements a helper object that `VsockMuxer` can use for queuing RX (host -> guest)
|
||||
/// packets (or rather instructions on how to build said packets).
|
||||
///
|
||||
/// Under ideal operation, every connection, that has pending RX data, will be present in the muxer
|
||||
/// RX queue. However, since the RX queue is smaller than the connection pool, it may, under some
|
||||
/// conditions, become full, meaning that it can no longer account for all the connections that can
|
||||
/// yield RX data. When that happens, we say that it is no longer "synchronized" (i.e. with the
|
||||
/// connection pool). A desynchronized RX queue still holds valid data, and the muxer will
|
||||
/// continue to pop packets from it. However, when a desynchronized queue is drained, additional
|
||||
/// data may still be available, so the muxer will have to perform a more costly walk of the entire
|
||||
/// connection pool to find it. This walk is performed here, as part of building an RX queue from
|
||||
/// the connection pool. When an out-of-sync is drained, the muxer will discard it, and attempt to
|
||||
/// rebuild a synced one.
|
||||
///
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use super::super::VsockChannel;
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
|
||||
mod address;
|
||||
mod gsi;
|
||||
/// page size related utility funtions
|
||||
pub mod page_size;
|
||||
mod system;
|
||||
|
||||
pub use crate::address::AddressAllocator;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright 2023 Arm Limited (or its affiliates). All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
|
||||
/// get host page size
|
||||
pub fn get_page_size() -> u64 {
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
unsafe { sysconf(_SC_PAGESIZE) as u64 }
|
||||
}
|
||||
|
||||
/// round up address to let it align page size
|
||||
pub fn align_page_size_up(address: u64) -> u64 {
|
||||
let page_size = get_page_size();
|
||||
(address + page_size - 1) & !(page_size - 1)
|
||||
}
|
||||
|
||||
/// round down address to let it align page size
|
||||
pub fn align_page_size_down(address: u64) -> u64 {
|
||||
let page_size = get_page_size();
|
||||
address & !(page_size - 1)
|
||||
}
|
||||
|
||||
/// Test if address is 4k aligned
|
||||
pub fn is_4k_aligned(address: u64) -> bool {
|
||||
(address & 0xfff) == 0
|
||||
}
|
||||
|
||||
/// Test if size is 4k aligned
|
||||
pub fn is_4k_multiple(size: u64) -> bool {
|
||||
(size & 0xfff) == 0
|
||||
}
|
||||
|
||||
/// Test if address is page size aligned
|
||||
pub fn is_page_size_aligned(address: u64) -> bool {
|
||||
let page_size = get_page_size();
|
||||
address & (page_size - 1) == 0
|
||||
}
|
||||
@@ -14,7 +14,14 @@ use crate::gsi::GsiAllocator;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::gsi::GsiApic;
|
||||
|
||||
use crate::page_size::get_page_size;
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
|
||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||
#[inline(always)]
|
||||
fn pagesize() -> usize {
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
unsafe { sysconf(_SC_PAGESIZE) as usize }
|
||||
}
|
||||
|
||||
/// Manages allocating system resources such as address space and interrupt numbers.
|
||||
///
|
||||
@@ -119,7 +126,7 @@ impl SystemAllocator {
|
||||
self.platform_mmio_address_space.allocate(
|
||||
address,
|
||||
size,
|
||||
Some(align_size.unwrap_or(get_page_size())),
|
||||
Some(align_size.unwrap_or(pagesize() as u64)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -133,7 +140,7 @@ impl SystemAllocator {
|
||||
self.mmio_hole_address_space.allocate(
|
||||
address,
|
||||
size,
|
||||
Some(align_size.unwrap_or(get_page_size())),
|
||||
Some(align_size.unwrap_or(pagesize() as u64)),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ kvm = ["vfio-ioctls/kvm"]
|
||||
mshv = ["vfio-ioctls/mshv"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
thiserror = "1.0.39"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.38"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap"] }
|
||||
vmm-sys-util = "0.11.0"
|
||||
|
||||
@@ -110,7 +110,8 @@ impl Bus {
|
||||
let devices = self.devices.read().unwrap();
|
||||
let (range, dev) = devices
|
||||
.range(..=BusRange { base: addr, len: 1 })
|
||||
.next_back()?;
|
||||
.rev()
|
||||
.next()?;
|
||||
dev.upgrade().map(|d| (*range, d.clone()))
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
thiserror = "1.0.39"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
versionize = "0.1.10"
|
||||
anyhow = "1.0.69"
|
||||
thiserror = "1.0.38"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic"] }
|
||||
|
||||
@@ -12,7 +12,7 @@ use versionize::{VersionMap, Versionize};
|
||||
pub mod protocol;
|
||||
|
||||
/// Global VMM version for versioning
|
||||
const MAJOR_VERSION: u16 = 32;
|
||||
const MAJOR_VERSION: u16 = 30;
|
||||
const MINOR_VERSION: u16 = 1;
|
||||
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ default = []
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.17"
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
||||
@@ -14,7 +14,7 @@ tracing = ["tracer/tracing"]
|
||||
|
||||
[dependencies]
|
||||
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
||||
anyhow = "1.0.70"
|
||||
anyhow = "1.0.69"
|
||||
arc-swap = "1.5.1"
|
||||
arch = { path = "../arch" }
|
||||
bitflags = "1.3.2"
|
||||
@@ -22,7 +22,7 @@ block_util = { path = "../block_util" }
|
||||
devices = { path = "../devices" }
|
||||
epoll = "4.3.1"
|
||||
event_monitor = { path = "../event_monitor" }
|
||||
gdbstub = { version = "0.6.4", optional = true }
|
||||
gdbstub = { version = "0.6.3", optional = true }
|
||||
gdbstub_arch = { version = "0.2.4", optional = true }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
libc = "0.2.139"
|
||||
@@ -35,24 +35,23 @@ option_parser = { path = "../option_parser" }
|
||||
pci = { path = "../pci" }
|
||||
qcow = { path = "../qcow" }
|
||||
seccompiler = "0.3.0"
|
||||
serde = { version = "1.0.156", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.96"
|
||||
serde = { version = "1.0.151", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.93"
|
||||
serial_buffer = { path = "../serial_buffer" }
|
||||
signal-hook = "0.3.15"
|
||||
thiserror = "1.0.39"
|
||||
signal-hook = "0.3.14"
|
||||
thiserror = "1.0.38"
|
||||
tracer = { path = "../tracer" }
|
||||
uuid = "1.3.0"
|
||||
versionize = "0.1.10"
|
||||
versionize = "0.1.9"
|
||||
versionize_derive = "0.1.4"
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
||||
vhdx = { path = "../vhdx" }
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
virtio-queue = "0.7.1"
|
||||
virtio-queue = "0.7.0"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
|
||||
zerocopy = "0.6.1"
|
||||
@@ -9,7 +9,7 @@ use crate::pci_segment::PciSegment;
|
||||
use crate::{GuestMemoryMmap, GuestRegionMmap};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use acpi_tables::sdt::GenericAddress;
|
||||
use acpi_tables::{rsdp::Rsdp, sdt::Sdt, Aml};
|
||||
use acpi_tables::{aml::Aml, rsdp::Rsdp, sdt::Sdt};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use arch::aarch64::DeviceInfoForFdt;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -20,8 +20,7 @@ use pci::PciBdf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use tracer::trace_scoped;
|
||||
use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryRegion};
|
||||
use zerocopy::AsBytes;
|
||||
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryRegion};
|
||||
|
||||
/* Values for Type in APIC sub-headers */
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -41,7 +40,7 @@ pub const ACPI_APIC_GENERIC_TRANSLATOR: u8 = 15;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct PciRangeEntry {
|
||||
pub base_address: u64,
|
||||
pub segment: u16,
|
||||
@@ -52,7 +51,7 @@ struct PciRangeEntry {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct MemoryAffinity {
|
||||
pub type_: u8,
|
||||
pub length: u8,
|
||||
@@ -69,7 +68,7 @@ struct MemoryAffinity {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct ProcessorLocalX2ApicAffinity {
|
||||
pub type_: u8,
|
||||
pub length: u8,
|
||||
@@ -83,7 +82,7 @@ struct ProcessorLocalX2ApicAffinity {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct ProcessorGiccAffinity {
|
||||
pub type_: u8,
|
||||
pub length: u8,
|
||||
@@ -143,7 +142,7 @@ impl MemoryAffinity {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct ViotVirtioPciNode {
|
||||
pub type_: u8,
|
||||
_reserved: u8,
|
||||
@@ -155,7 +154,7 @@ struct ViotVirtioPciNode {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct ViotPciRangeNode {
|
||||
pub type_: u8,
|
||||
_reserved: u8,
|
||||
@@ -180,9 +179,9 @@ pub fn create_dsdt_table(
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
device_manager.lock().unwrap().to_aml_bytes(&mut bytes);
|
||||
cpu_manager.lock().unwrap().to_aml_bytes(&mut bytes);
|
||||
memory_manager.lock().unwrap().to_aml_bytes(&mut bytes);
|
||||
device_manager.lock().unwrap().append_aml_bytes(&mut bytes);
|
||||
cpu_manager.lock().unwrap().append_aml_bytes(&mut bytes);
|
||||
memory_manager.lock().unwrap().append_aml_bytes(&mut bytes);
|
||||
dsdt.append_slice(&bytes);
|
||||
|
||||
dsdt
|
||||
@@ -239,7 +238,7 @@ fn create_facp_table(dsdt_offset: GuestAddress, device_manager: &Arc<Mutex<Devic
|
||||
// X_DSDT
|
||||
facp.write(140, dsdt_offset.0);
|
||||
// Hypervisor Vendor Identity
|
||||
facp.write_bytes(268, b"CLOUDHYP");
|
||||
facp.write(268, b"CLOUDHYP");
|
||||
|
||||
facp.update_checksum();
|
||||
|
||||
@@ -812,7 +811,7 @@ pub fn create_acpi_tables(
|
||||
// RSDP
|
||||
let rsdp = Rsdp::new(*b"CLOUDH", xsdt_offset.0);
|
||||
guest_mem
|
||||
.write_slice(rsdp.as_bytes(), rsdp_offset)
|
||||
.write_slice(rsdp.as_slice(), rsdp_offset)
|
||||
.expect("Error writing RSDP");
|
||||
|
||||
info!(
|
||||
|
||||
@@ -36,22 +36,13 @@ impl EndpointHandler for VmCreate {
|
||||
match &req.body {
|
||||
Some(body) => {
|
||||
// Deserialize into a VmConfig
|
||||
let mut vm_config: VmConfig = match serde_json::from_slice(body.raw())
|
||||
let vm_config: VmConfig = match serde_json::from_slice(body.raw())
|
||||
.map_err(HttpError::SerdeJsonDeserialize)
|
||||
{
|
||||
Ok(config) => config,
|
||||
Err(e) => return error_response(e, StatusCode::BadRequest),
|
||||
};
|
||||
|
||||
if let Some(ref mut nets) = vm_config.net {
|
||||
if nets.iter().any(|net| net.fds.is_some()) {
|
||||
warn!("Ignoring FDs sent via the HTTP request body");
|
||||
}
|
||||
for net in nets {
|
||||
net.fds = None;
|
||||
}
|
||||
}
|
||||
|
||||
// Call vm_create()
|
||||
match vm_create(api_notifier, api_sender, Arc::new(Mutex::new(vm_config)))
|
||||
.map_err(HttpError::ApiError)
|
||||
|
||||
@@ -165,9 +165,7 @@ pub struct VmInfo {
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct VmmPingResponse {
|
||||
pub build_version: String,
|
||||
pub version: String,
|
||||
pub pid: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, Default, Debug)]
|
||||
@@ -232,6 +230,7 @@ pub enum ApiResponsePayload {
|
||||
/// This is the response sent by the VMM API server through the mpsc channel.
|
||||
pub type ApiResponse = std::result::Result<ApiResponsePayload, ApiError>;
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug)]
|
||||
pub enum ApiRequest {
|
||||
/// Create the virtual machine. This request payload is a VM configuration
|
||||
|
||||
@@ -438,13 +438,8 @@ components:
|
||||
- version
|
||||
type: object
|
||||
properties:
|
||||
build_version:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
pid:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Virtual Machine Monitor information
|
||||
|
||||
VmInfo:
|
||||
|
||||
@@ -17,7 +17,7 @@ use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
use virtio_devices::{RateLimiterConfig, TokenBucketConfig};
|
||||
|
||||
const MAX_NUM_PCI_SEGMENTS: u16 = 96;
|
||||
const MAX_NUM_PCI_SEGMENTS: u16 = 16;
|
||||
|
||||
/// Errors associated with VM configuration parameters.
|
||||
#[derive(Debug, Error)]
|
||||
@@ -2947,26 +2947,24 @@ mod tests {
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
..Default::default()
|
||||
});
|
||||
assert!(still_valid_config.validate().is_ok());
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS + 1,
|
||||
num_pci_segments: 17,
|
||||
..Default::default()
|
||||
});
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::InvalidNumPciSegments(
|
||||
MAX_NUM_PCI_SEGMENTS + 1
|
||||
))
|
||||
Err(ValidationError::InvalidNumPciSegments(17))
|
||||
);
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -2974,18 +2972,18 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
iommu_segments: Some(vec![MAX_NUM_PCI_SEGMENTS + 1, MAX_NUM_PCI_SEGMENTS + 2]),
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![17, 18]),
|
||||
..Default::default()
|
||||
});
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::InvalidPciSegment(MAX_NUM_PCI_SEGMENTS + 1))
|
||||
Err(ValidationError::InvalidPciSegment(17))
|
||||
);
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -2998,7 +2996,7 @@ mod tests {
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3011,7 +3009,7 @@ mod tests {
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3024,7 +3022,7 @@ mod tests {
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3037,7 +3035,7 @@ mod tests {
|
||||
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3050,7 +3048,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3066,7 +3064,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3082,7 +3080,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3098,7 +3096,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3114,7 +3112,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3131,7 +3129,7 @@ mod tests {
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.memory.shared = true;
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3146,7 +3144,7 @@ mod tests {
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
@@ -3162,7 +3160,7 @@ mod tests {
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.memory.shared = true;
|
||||
invalid_config.platform = Some(PlatformConfig {
|
||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||
num_pci_segments: 16,
|
||||
iommu_segments: Some(vec![1, 2, 3]),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::vm::physical_bits;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::CPU_MANAGER_SNAPSHOT_ID;
|
||||
use acpi_tables::{aml, sdt::Sdt, Aml};
|
||||
use acpi_tables::{aml, aml::Aml, sdt::Sdt};
|
||||
use anyhow::anyhow;
|
||||
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
|
||||
use arch::aarch64::regs;
|
||||
@@ -84,7 +84,6 @@ use vm_migration::{
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::signal::{register_signal_handler, SIGRTMIN};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
|
||||
/// Extract the specified bits of a 64-bit integer.
|
||||
@@ -168,16 +167,12 @@ pub enum Error {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[error("Error setting up AMX: {0}")]
|
||||
AmxEnable(#[source] anyhow::Error),
|
||||
|
||||
#[error("Maximum number of vCPUs exceeds host limit")]
|
||||
MaximumVcpusExceeded,
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct LocalApic {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -188,7 +183,7 @@ struct LocalApic {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct Ioapic {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -201,7 +196,6 @@ struct Ioapic {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct GicC {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -226,7 +220,6 @@ struct GicC {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct GicD {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -241,7 +234,6 @@ struct GicD {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct GicR {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -253,7 +245,6 @@ struct GicR {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct GicIts {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -266,7 +257,6 @@ struct GicIts {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(AsBytes)]
|
||||
struct ProcessorHierarchyNode {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -279,7 +269,7 @@ struct ProcessorHierarchyNode {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Default, AsBytes)]
|
||||
#[derive(Default)]
|
||||
struct InterruptSourceOverride {
|
||||
pub r#type: u8,
|
||||
pub length: u8,
|
||||
@@ -599,10 +589,6 @@ impl CpuManager {
|
||||
#[cfg(feature = "tdx")] tdx_enabled: bool,
|
||||
numa_nodes: &NumaNodes,
|
||||
) -> Result<Arc<Mutex<CpuManager>>> {
|
||||
if u32::from(config.max_vcpus) > hypervisor.get_max_vcpus() {
|
||||
return Err(Error::MaximumVcpusExceeded);
|
||||
}
|
||||
|
||||
let mut vcpu_states = Vec::with_capacity(usize::from(config.max_vcpus));
|
||||
vcpu_states.resize_with(usize::from(config.max_vcpus), VcpuState::default);
|
||||
let hypervisor_type = hypervisor.hypervisor_type();
|
||||
@@ -703,23 +689,14 @@ impl CpuManager {
|
||||
.sgx_epc_region()
|
||||
.as_ref()
|
||||
.map(|sgx_epc_region| sgx_epc_region.epc_sections().values().cloned().collect());
|
||||
|
||||
let topology = self.config.topology.clone().map_or_else(
|
||||
|| {
|
||||
#[cfg(feature = "mshv")]
|
||||
if matches!(hypervisor.hypervisor_type(), HypervisorType::Mshv) {
|
||||
return Some((1, self.boot_vcpus(), 1));
|
||||
}
|
||||
None
|
||||
},
|
||||
|t| Some((t.threads_per_core, t.cores_per_die, t.dies_per_package)),
|
||||
);
|
||||
|
||||
self.cpuid = {
|
||||
let phys_bits = physical_bits(self.config.max_phys_bits);
|
||||
arch::generate_common_cpuid(
|
||||
hypervisor,
|
||||
topology,
|
||||
self.config
|
||||
.topology
|
||||
.clone()
|
||||
.map(|t| (t.threads_per_core, t.cores_per_die, t.dies_per_package)),
|
||||
sgx_epc_sections,
|
||||
phys_bits,
|
||||
self.config.kvm_hyperv,
|
||||
@@ -1131,7 +1108,7 @@ impl CpuManager {
|
||||
|
||||
fn remove_vcpu(&mut self, cpu_id: u8) -> Result<()> {
|
||||
info!("Removing vCPU: cpu_id = {}", cpu_id);
|
||||
let state = &mut self.vcpu_states[usize::from(cpu_id)];
|
||||
let mut state = &mut self.vcpu_states[usize::from(cpu_id)];
|
||||
state.kill.store(true, Ordering::SeqCst);
|
||||
state.signal_thread();
|
||||
state.join_thread()?;
|
||||
@@ -1283,7 +1260,7 @@ impl CpuManager {
|
||||
let mut madt = Sdt::new(*b"APIC", 44, 5, *b"CLOUDH", *b"CHMADT ", 1);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
madt.write(36, arch::layout::APIC_START.0);
|
||||
madt.write(36, arch::layout::APIC_START);
|
||||
|
||||
for cpu in 0..self.config.max_vcpus {
|
||||
let lapic = LocalApic {
|
||||
@@ -1749,7 +1726,7 @@ impl Cpu {
|
||||
}
|
||||
|
||||
impl Aml for Cpu {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let mat_data: Vec<u8> = self.generate_mat();
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
@@ -1790,7 +1767,7 @@ impl Aml for Cpu {
|
||||
// containing the LAPIC for this processor with the enabled bit set
|
||||
// even it if is disabled in the MADT (non-boot CPU)
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::Name::new("_MAT".into(), &aml::BufferData::new(mat_data)),
|
||||
&aml::Name::new("_MAT".into(), &aml::Buffer::new(mat_data)),
|
||||
// Trigger CPU ejection
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::Method::new(
|
||||
@@ -1802,7 +1779,7 @@ impl Aml for Cpu {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
} else {
|
||||
aml::Device::new(
|
||||
format!("C{:03}", self.cpu_id).as_str().into(),
|
||||
@@ -1827,10 +1804,10 @@ impl Aml for Cpu {
|
||||
// containing the LAPIC for this processor with the enabled bit set
|
||||
// even it if is disabled in the MADT (non-boot CPU)
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::Name::new("_MAT".into(), &aml::BufferData::new(mat_data)),
|
||||
&aml::Name::new("_MAT".into(), &aml::Buffer::new(mat_data)),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1840,13 +1817,13 @@ struct CpuNotify {
|
||||
}
|
||||
|
||||
impl Aml for CpuNotify {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let object = aml::Path::new(&format!("C{:03}", self.cpu_id));
|
||||
aml::If::new(
|
||||
&aml::Equal::new(&aml::Arg(0), &self.cpu_id),
|
||||
vec![&aml::Notify::new(&object, &aml::Arg(1))],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1856,7 +1833,7 @@ struct CpuMethods {
|
||||
}
|
||||
|
||||
impl Aml for CpuMethods {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
if self.dynamic {
|
||||
// CPU status method
|
||||
aml::Method::new(
|
||||
@@ -1880,19 +1857,19 @@ impl Aml for CpuMethods {
|
||||
&aml::Return::new(&aml::Local(0)),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
let mut cpu_notifies = Vec::new();
|
||||
for cpu_id in 0..self.max_vcpus {
|
||||
cpu_notifies.push(CpuNotify { cpu_id });
|
||||
}
|
||||
|
||||
let mut cpu_notifies_refs: Vec<&dyn Aml> = Vec::new();
|
||||
let mut cpu_notifies_refs: Vec<&dyn aml::Aml> = Vec::new();
|
||||
for cpu_id in 0..self.max_vcpus {
|
||||
cpu_notifies_refs.push(&cpu_notifies[usize::from(cpu_id)]);
|
||||
}
|
||||
|
||||
aml::Method::new("CTFY".into(), 2, true, cpu_notifies_refs).to_aml_bytes(sink);
|
||||
aml::Method::new("CTFY".into(), 2, true, cpu_notifies_refs).append_aml_bytes(bytes);
|
||||
|
||||
aml::Method::new(
|
||||
"CEJ0".into(),
|
||||
@@ -1907,7 +1884,7 @@ impl Aml for CpuMethods {
|
||||
&aml::Release::new("\\_SB_.PRES.CPLK".into()),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
aml::Method::new(
|
||||
"CSCN".into(),
|
||||
@@ -1961,22 +1938,22 @@ impl Aml for CpuMethods {
|
||||
&aml::Release::new("\\_SB_.PRES.CPLK".into()),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
} else {
|
||||
aml::Method::new("CSCN".into(), 0, true, vec![]).to_aml_bytes(sink)
|
||||
aml::Method::new("CSCN".into(), 0, true, vec![]).append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Aml for CpuManager {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
if let Some(acpi_address) = self.acpi_address {
|
||||
// CPU hotplug controller
|
||||
aml::Device::new(
|
||||
"_SB_.PRES".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
||||
&aml::Name::new("_UID".into(), &"CPU Hotplug Controller"),
|
||||
// Mutex to protect concurrent access as we write to choose CPU and then read back status
|
||||
&aml::Mutex::new("CPLK".into(), 0),
|
||||
@@ -1993,13 +1970,12 @@ impl Aml for CpuManager {
|
||||
&aml::OpRegion::new(
|
||||
"PRST".into(),
|
||||
aml::OpRegionSpace::SystemMemory,
|
||||
&(acpi_address.0 as usize),
|
||||
&CPU_MANAGER_ACPI_SIZE,
|
||||
acpi_address.0 as usize,
|
||||
CPU_MANAGER_ACPI_SIZE,
|
||||
),
|
||||
&aml::Field::new(
|
||||
"PRST".into(),
|
||||
aml::FieldAccessType::Byte,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::WriteAsZeroes,
|
||||
vec![
|
||||
aml::FieldEntry::Reserved(32),
|
||||
@@ -2014,7 +1990,6 @@ impl Aml for CpuManager {
|
||||
&aml::Field::new(
|
||||
"PRST".into(),
|
||||
aml::FieldAccessType::DWord,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::Preserve,
|
||||
vec![
|
||||
aml::FieldEntry::Named(*b"CSEL", 32),
|
||||
@@ -2024,18 +1999,18 @@ impl Aml for CpuManager {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
|
||||
// CPU devices
|
||||
let hid = aml::Name::new("_HID".into(), &"ACPI0010");
|
||||
let uid = aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0A05"));
|
||||
let uid = aml::Name::new("_CID".into(), &aml::EisaName::new("PNP0A05"));
|
||||
// Bundle methods together under a common object
|
||||
let methods = CpuMethods {
|
||||
max_vcpus: self.config.max_vcpus,
|
||||
dynamic: self.dynamic,
|
||||
};
|
||||
let mut cpu_data_inner: Vec<&dyn Aml> = vec![&hid, &uid, &methods];
|
||||
let mut cpu_data_inner: Vec<&dyn aml::Aml> = vec![&hid, &uid, &methods];
|
||||
|
||||
let mut cpu_devices = Vec::new();
|
||||
for cpu_id in 0..self.config.max_vcpus {
|
||||
@@ -2053,7 +2028,7 @@ impl Aml for CpuManager {
|
||||
cpu_data_inner.push(cpu_device);
|
||||
}
|
||||
|
||||
aml::Device::new("_SB_.CPUS".into(), cpu_data_inner).to_aml_bytes(sink)
|
||||
aml::Device::new("_SB_.CPUS".into(), cpu_data_inner).append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::GuestRegionMmap;
|
||||
use crate::PciDeviceInfo;
|
||||
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
||||
use acpi_tables::sdt::GenericAddress;
|
||||
use acpi_tables::{aml, Aml};
|
||||
use acpi_tables::{aml, aml::Aml};
|
||||
use anyhow::anyhow;
|
||||
use arch::layout;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -70,6 +70,7 @@ use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use tracer::trace_scoped;
|
||||
@@ -100,6 +101,7 @@ use vm_migration::{
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vm_virtio::VirtioDeviceType;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::terminal::Terminal;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
const MMIO_LEN: u64 = 0x1000;
|
||||
@@ -530,14 +532,6 @@ pub struct Console {
|
||||
}
|
||||
|
||||
impl Console {
|
||||
pub fn need_resize(&self) -> bool {
|
||||
if let Some(_resizer) = self.console_resizer.as_ref() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn update_console_size(&self) {
|
||||
if let Some(resizer) = self.console_resizer.as_ref() {
|
||||
resizer.update_console_size()
|
||||
@@ -831,8 +825,8 @@ pub struct DeviceManager {
|
||||
// pty foreground status,
|
||||
console_resize_pipe: Option<Arc<File>>,
|
||||
|
||||
// To restore on exit.
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
// Are any devices using the tty?
|
||||
on_tty: Option<Arc<AtomicBool>>,
|
||||
|
||||
// Interrupt controller
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -1118,7 +1112,7 @@ impl DeviceManager {
|
||||
serial_manager: None,
|
||||
console_pty: None,
|
||||
console_resize_pipe: None,
|
||||
original_termios_opt: Arc::new(Mutex::new(None)),
|
||||
on_tty: None,
|
||||
virtio_mem_devices: Vec::new(),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
gpio_device: None,
|
||||
@@ -1166,7 +1160,7 @@ impl DeviceManager {
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
on_tty: Arc<AtomicBool>,
|
||||
) -> DeviceManagerResult<()> {
|
||||
trace_scoped!("create_devices");
|
||||
|
||||
@@ -1222,15 +1216,15 @@ impl DeviceManager {
|
||||
)?;
|
||||
}
|
||||
|
||||
self.original_termios_opt = original_termios_opt;
|
||||
|
||||
self.console = self.add_console_device(
|
||||
&legacy_interrupt_manager,
|
||||
&mut virtio_devices,
|
||||
serial_pty,
|
||||
console_pty,
|
||||
console_resize_pipe,
|
||||
&on_tty,
|
||||
)?;
|
||||
self.on_tty = Some(on_tty);
|
||||
|
||||
if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() {
|
||||
let tpm_dev = self.add_tpm_device(tpm.socket.clone())?;
|
||||
@@ -1843,7 +1837,7 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
fn modify_mode<F: FnOnce(&mut termios)>(
|
||||
&mut self,
|
||||
&self,
|
||||
fd: RawFd,
|
||||
f: F,
|
||||
) -> vmm_sys_util::errno::Result<()> {
|
||||
@@ -1860,10 +1854,6 @@ impl DeviceManager {
|
||||
if ret < 0 {
|
||||
return vmm_sys_util::errno::errno_result();
|
||||
}
|
||||
let mut original_termios_opt = self.original_termios_opt.lock().unwrap();
|
||||
if original_termios_opt.is_none() {
|
||||
*original_termios_opt = Some(termios);
|
||||
}
|
||||
f(&mut termios);
|
||||
// SAFETY: Safe because the syscall will only read the extent of termios and we check
|
||||
// the return result.
|
||||
@@ -1875,12 +1865,12 @@ impl DeviceManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_raw_mode(&mut self, f: &mut dyn AsRawFd) -> vmm_sys_util::errno::Result<()> {
|
||||
fn set_raw_mode(&self, f: &mut dyn AsRawFd) -> vmm_sys_util::errno::Result<()> {
|
||||
// SAFETY: FFI call. Variable t is guaranteed to be a valid termios from modify_mode.
|
||||
self.modify_mode(f.as_raw_fd(), |t| unsafe { cfmakeraw(t) })
|
||||
}
|
||||
|
||||
fn listen_for_sigwinch_on_tty(&mut self, pty_sub: File) -> std::io::Result<()> {
|
||||
fn listen_for_sigwinch_on_tty(&mut self, pty_main: File, pty_sub: File) -> std::io::Result<()> {
|
||||
let seccomp_filter = get_seccomp_filter(
|
||||
&self.seccomp_action,
|
||||
Thread::PtyForeground,
|
||||
@@ -1888,8 +1878,14 @@ impl DeviceManager {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self.console_resize_pipe =
|
||||
Some(Arc::new(start_sigwinch_listener(seccomp_filter, pty_sub)?));
|
||||
match start_sigwinch_listener(seccomp_filter, pty_main, pty_sub) {
|
||||
Ok(pipe) => {
|
||||
self.console_resize_pipe = Some(Arc::new(pipe));
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Ignoring error from setting up SIGWINCH listener: {}", e)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1899,6 +1895,7 @@ impl DeviceManager {
|
||||
virtio_devices: &mut Vec<MetaVirtioDevice>,
|
||||
console_pty: Option<PtyPair>,
|
||||
resize_pipe: Option<File>,
|
||||
on_tty: &Arc<AtomicBool>,
|
||||
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
|
||||
let console_config = self.config.lock().unwrap().console.clone();
|
||||
let endpoint = match console_config.mode {
|
||||
@@ -1922,7 +1919,8 @@ impl DeviceManager {
|
||||
self.config.lock().unwrap().console.file = Some(path.clone());
|
||||
let file = main.try_clone().unwrap();
|
||||
assert!(resize_pipe.is_none());
|
||||
self.listen_for_sigwinch_on_tty(sub).unwrap();
|
||||
self.listen_for_sigwinch_on_tty(main.try_clone().unwrap(), sub)
|
||||
.unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
|
||||
Endpoint::PtyPair(file.try_clone().unwrap(), file)
|
||||
}
|
||||
@@ -1939,15 +1937,11 @@ impl DeviceManager {
|
||||
// SAFETY: stdout is valid and owned solely by us.
|
||||
let mut stdout = unsafe { File::from_raw_fd(stdout) };
|
||||
|
||||
on_tty.store(true, Ordering::SeqCst);
|
||||
|
||||
// Make sure stdout is in raw mode, if it's a terminal.
|
||||
let _ = self.set_raw_mode(&mut stdout);
|
||||
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
if unsafe { libc::isatty(libc::STDOUT_FILENO) } == 1 {
|
||||
self.listen_for_sigwinch_on_tty(stdout.try_clone().unwrap())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// If an interactive TTY then we can accept input
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
|
||||
@@ -2018,6 +2012,7 @@ impl DeviceManager {
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
console_resize_pipe: Option<File>,
|
||||
on_tty: &Arc<AtomicBool>,
|
||||
) -> DeviceManagerResult<Arc<Console>> {
|
||||
let serial_config = self.config.lock().unwrap().serial.clone();
|
||||
let serial_writer: Option<Box<dyn io::Write + Send>> = match serial_config.mode {
|
||||
@@ -2041,6 +2036,7 @@ impl DeviceManager {
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
let mut out = stdout();
|
||||
on_tty.store(true, Ordering::SeqCst);
|
||||
let _ = self.set_raw_mode(&mut out);
|
||||
Some(Box::new(out))
|
||||
}
|
||||
@@ -2070,8 +2066,12 @@ impl DeviceManager {
|
||||
};
|
||||
}
|
||||
|
||||
let console_resizer =
|
||||
self.add_virtio_console_device(virtio_devices, console_pty, console_resize_pipe)?;
|
||||
let console_resizer = self.add_virtio_console_device(
|
||||
virtio_devices,
|
||||
console_pty,
|
||||
console_resize_pipe,
|
||||
on_tty,
|
||||
)?;
|
||||
|
||||
Ok(Arc::new(Console { console_resizer }))
|
||||
}
|
||||
@@ -4250,7 +4250,7 @@ fn numa_node_id_from_memory_zone_id(numa_nodes: &NumaNodes, memory_zone_id: &str
|
||||
struct TpmDevice {}
|
||||
|
||||
impl Aml for TpmDevice {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn to_aml_bytes(&self) -> Vec<u8> {
|
||||
aml::Device::new(
|
||||
"TPM2".into(),
|
||||
vec![
|
||||
@@ -4266,19 +4266,19 @@ impl Aml for TpmDevice {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.to_aml_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Aml for DeviceManager {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use arch::aarch64::DeviceInfoForFdt;
|
||||
|
||||
let mut pci_scan_methods = Vec::new();
|
||||
for i in 0..self.pci_segments.len() {
|
||||
pci_scan_methods.push(aml::MethodCall::new(
|
||||
format!("\\_SB_.PC{i:02X}.PCNT").as_str().into(),
|
||||
format!("\\_SB_.PCI{i:X}.PCNT").as_str().into(),
|
||||
vec![],
|
||||
));
|
||||
}
|
||||
@@ -4291,7 +4291,7 @@ impl Aml for DeviceManager {
|
||||
aml::Device::new(
|
||||
"_SB_.PHPR".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
||||
&aml::Name::new("_STA".into(), &0x0bu8),
|
||||
&aml::Name::new("_UID".into(), &"PCI Hotplug Controller"),
|
||||
&aml::Mutex::new("BLCK".into(), 0),
|
||||
@@ -4308,13 +4308,12 @@ impl Aml for DeviceManager {
|
||||
&aml::OpRegion::new(
|
||||
"PCST".into(),
|
||||
aml::OpRegionSpace::SystemMemory,
|
||||
&(self.acpi_address.0 as usize),
|
||||
&DEVICE_MANAGER_ACPI_SIZE,
|
||||
self.acpi_address.0 as usize,
|
||||
DEVICE_MANAGER_ACPI_SIZE,
|
||||
),
|
||||
&aml::Field::new(
|
||||
"PCST".into(),
|
||||
aml::FieldAccessType::DWord,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::WriteAsZeroes,
|
||||
vec![
|
||||
aml::FieldEntry::Named(*b"PCIU", 32),
|
||||
@@ -4343,10 +4342,10 @@ impl Aml for DeviceManager {
|
||||
&aml::Method::new("PSCN".into(), 0, true, pci_scan_inner),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
for segment in &self.pci_segments {
|
||||
segment.to_aml_bytes(sink);
|
||||
segment.append_aml_bytes(bytes);
|
||||
}
|
||||
|
||||
let mut mbrd_memory = Vec::new();
|
||||
@@ -4367,12 +4366,12 @@ impl Aml for DeviceManager {
|
||||
aml::Device::new(
|
||||
"_SB_.MBRD".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0C02")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0C02")),
|
||||
&aml::Name::new("_UID".into(), &aml::ZERO),
|
||||
&aml::Name::new("_CRS".into(), &aml::ResourceTemplate::new(mbrd_memory_refs)),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
// Serial device
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -4396,7 +4395,7 @@ impl Aml for DeviceManager {
|
||||
&aml::Name::new(
|
||||
"_HID".into(),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::EISAName::new("PNP0501"),
|
||||
&aml::EisaName::new("PNP0501"),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
&"ARMH0011",
|
||||
),
|
||||
@@ -4407,7 +4406,7 @@ impl Aml for DeviceManager {
|
||||
&aml::ResourceTemplate::new(vec![
|
||||
&aml::Interrupt::new(true, true, false, false, serial_irq),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::IO::new(0x3f8, 0x3f8, 0, 0x8),
|
||||
&aml::Io::new(0x3f8, 0x3f8, 0, 0x8),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
&aml::Memory32Fixed::new(
|
||||
true,
|
||||
@@ -4418,23 +4417,25 @@ impl Aml for DeviceManager {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
|
||||
aml::Name::new("_S5_".into(), &aml::Package::new(vec![&5u8])).to_aml_bytes(sink);
|
||||
aml::Name::new("_S5_".into(), &aml::Package::new(vec![&5u8])).append_aml_bytes(bytes);
|
||||
|
||||
aml::Device::new(
|
||||
"_SB_.PWRB".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0C0C")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0C0C")),
|
||||
&aml::Name::new("_UID".into(), &aml::ZERO),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
if self.config.lock().unwrap().tpm.is_some() {
|
||||
// Add tpm device
|
||||
TpmDevice {}.to_aml_bytes(sink);
|
||||
let tpm_acpi = TpmDevice {};
|
||||
let tpm_dsdt_data = tpm_acpi.to_aml_bytes();
|
||||
bytes.extend_from_slice(tpm_dsdt_data.as_slice());
|
||||
}
|
||||
|
||||
self.ged_notification_device
|
||||
@@ -4442,7 +4443,7 @@ impl Aml for DeviceManager {
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4655,9 +4656,10 @@ impl Drop for DeviceManager {
|
||||
handle.virtio_device.lock().unwrap().shutdown();
|
||||
}
|
||||
|
||||
if let Some(termios) = *self.original_termios_opt.lock().unwrap() {
|
||||
// SAFETY: FFI call
|
||||
let _ = unsafe { tcsetattr(stdout().lock().as_raw_fd(), TCSANOW, &termios) };
|
||||
if let Some(ref on_tty) = self.on_tty {
|
||||
if on_tty.load(Ordering::SeqCst) {
|
||||
let _ = std::io::stdin().lock().set_canon_mode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,8 +109,7 @@ pub struct BftIter<'a> {
|
||||
|
||||
impl<'a> BftIter<'a> {
|
||||
fn new(hash_map: &'a HashMap<String, DeviceNode>) -> Self {
|
||||
let mut nodes = Vec::with_capacity(hash_map.len());
|
||||
let mut i = 0;
|
||||
let mut nodes = Vec::new();
|
||||
|
||||
for (_, node) in hash_map.iter() {
|
||||
if node.parent.is_none() {
|
||||
@@ -118,13 +117,26 @@ impl<'a> BftIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
while i < nodes.len() {
|
||||
for child_node_id in nodes[i].children.iter() {
|
||||
if let Some(child_node) = hash_map.get(child_node_id) {
|
||||
nodes.push(child_node);
|
||||
let mut node_layer = nodes.as_slice();
|
||||
loop {
|
||||
let mut next_node_layer = Vec::new();
|
||||
|
||||
for node in node_layer.iter() {
|
||||
for child_node_id in node.children.iter() {
|
||||
if let Some(child_node) = hash_map.get(child_node_id) {
|
||||
next_node_layer.push(child_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
|
||||
if next_node_layer.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let pos = nodes.len();
|
||||
nodes.extend(next_node_layer);
|
||||
|
||||
node_layer = &nodes[pos..];
|
||||
}
|
||||
|
||||
BftIter { nodes }
|
||||
|
||||
@@ -435,6 +435,7 @@ impl run_blocking::BlockingEventLoop for GdbEventLoop {
|
||||
type Connection = Box<dyn ConnectionExt<Error = std::io::Error>>;
|
||||
type StopReason = MultiThreadStopReason<ArchUsize>;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn wait_for_stop_reason(
|
||||
target: &mut Self::Target,
|
||||
conn: &mut Self::Connection,
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::migration::{recv_vm_config, recv_vm_state};
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::vm::{Error as VmError, Vm, VmState};
|
||||
use anyhow::anyhow;
|
||||
use libc::{tcsetattr, termios, EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW};
|
||||
use libc::{EFD_NONBLOCK, SIGINT, SIGTERM};
|
||||
use memory_manager::MemoryManagerSnapshotData;
|
||||
use pci::PciBdf;
|
||||
use seccompiler::{apply_filter, SeccompAction};
|
||||
@@ -35,12 +35,13 @@ use signal_hook::iterator::{Handle, Signals};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{stdout, Read, Write};
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
@@ -53,6 +54,7 @@ use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, Transport
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::signal::unblock_signal;
|
||||
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
|
||||
use vmm_sys_util::terminal::Terminal;
|
||||
|
||||
mod acpi;
|
||||
pub mod api;
|
||||
@@ -80,6 +82,7 @@ type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>;
|
||||
|
||||
/// Errors associated with VMM management
|
||||
#[derive(Debug, Error)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Error {
|
||||
/// API request receive error
|
||||
#[error("Error receiving API request: {0}")]
|
||||
@@ -279,7 +282,7 @@ impl Serialize for PciDeviceInfo {
|
||||
#[allow(unused_variables)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn start_vmm_thread(
|
||||
vmm_version: VmmVersionInfo,
|
||||
vmm_version: String,
|
||||
http_path: &Option<String>,
|
||||
http_fd: Option<RawFd>,
|
||||
api_event: EventFd,
|
||||
@@ -288,7 +291,6 @@ pub fn start_vmm_thread(
|
||||
#[cfg(feature = "guest_debug")] debug_path: Option<PathBuf>,
|
||||
#[cfg(feature = "guest_debug")] debug_event: EventFd,
|
||||
#[cfg(feature = "guest_debug")] vm_debug_event: EventFd,
|
||||
exit_event: EventFd,
|
||||
seccomp_action: &SeccompAction,
|
||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
) -> Result<thread::JoinHandle<Result<()>>> {
|
||||
@@ -309,8 +311,9 @@ pub fn start_vmm_thread(
|
||||
.map_err(Error::CreateSeccompFilter)?;
|
||||
|
||||
let vmm_seccomp_action = seccomp_action.clone();
|
||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
let thread = {
|
||||
let exit_event = exit_event.try_clone().map_err(Error::EventFdClone)?;
|
||||
let exit_evt = exit_evt.try_clone().map_err(Error::EventFdClone)?;
|
||||
thread::Builder::new()
|
||||
.name("vmm".to_string())
|
||||
.spawn(move || {
|
||||
@@ -320,7 +323,7 @@ pub fn start_vmm_thread(
|
||||
}
|
||||
|
||||
let mut vmm = Vmm::new(
|
||||
vmm_version,
|
||||
vmm_version.to_string(),
|
||||
api_event,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_event,
|
||||
@@ -328,7 +331,7 @@ pub fn start_vmm_thread(
|
||||
vm_debug_event,
|
||||
vmm_seccomp_action,
|
||||
hypervisor,
|
||||
exit_event,
|
||||
exit_evt,
|
||||
)?;
|
||||
|
||||
vmm.setup_signal_handler()?;
|
||||
@@ -349,7 +352,7 @@ pub fn start_vmm_thread(
|
||||
http_api_event,
|
||||
api_sender,
|
||||
seccomp_action,
|
||||
exit_event,
|
||||
exit_evt,
|
||||
hypervisor_type,
|
||||
)?;
|
||||
} else if let Some(http_fd) = http_fd {
|
||||
@@ -358,7 +361,7 @@ pub fn start_vmm_thread(
|
||||
http_api_event,
|
||||
api_sender,
|
||||
seccomp_action,
|
||||
exit_event,
|
||||
exit_evt,
|
||||
hypervisor_type,
|
||||
)?;
|
||||
}
|
||||
@@ -388,21 +391,6 @@ struct VmMigrationConfig {
|
||||
memory_manager_data: MemoryManagerSnapshotData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VmmVersionInfo {
|
||||
pub build_version: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
impl VmmVersionInfo {
|
||||
pub fn new(build_version: &str, version: &str) -> Self {
|
||||
Self {
|
||||
build_version: build_version.to_owned(),
|
||||
version: version.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Vmm {
|
||||
epoll: EpollContext,
|
||||
exit_evt: EventFd,
|
||||
@@ -412,7 +400,7 @@ pub struct Vmm {
|
||||
debug_evt: EventFd,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
vm_debug_evt: EventFd,
|
||||
version: VmmVersionInfo,
|
||||
version: String,
|
||||
vm: Option<Vm>,
|
||||
vm_config: Option<Arc<Mutex<VmConfig>>>,
|
||||
seccomp_action: SeccompAction,
|
||||
@@ -420,17 +408,13 @@ pub struct Vmm {
|
||||
activate_evt: EventFd,
|
||||
signals: Option<Handle>,
|
||||
threads: Vec<thread::JoinHandle<()>>,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
on_tty: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Vmm {
|
||||
pub const HANDLED_SIGNALS: [i32; 2] = [SIGTERM, SIGINT];
|
||||
|
||||
fn signal_handler(
|
||||
mut signals: Signals,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
exit_evt: &EventFd,
|
||||
) {
|
||||
fn signal_handler(mut signals: Signals, on_tty: Arc<AtomicBool>, exit_evt: &EventFd) {
|
||||
for sig in &Self::HANDLED_SIGNALS {
|
||||
unblock_signal(*sig).unwrap();
|
||||
}
|
||||
@@ -440,17 +424,12 @@ impl Vmm {
|
||||
SIGTERM | SIGINT => {
|
||||
if exit_evt.write(1).is_err() {
|
||||
// Resetting the terminal is usually done as the VMM exits
|
||||
if let Ok(lock) = original_termios_opt.lock() {
|
||||
if let Some(termios) = *lock {
|
||||
// SAFETY: FFI call
|
||||
let _ = unsafe {
|
||||
tcsetattr(stdout().lock().as_raw_fd(), TCSANOW, &termios)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
warn!("Failed to lock original termios");
|
||||
if on_tty.load(Ordering::SeqCst) {
|
||||
io::stdin()
|
||||
.lock()
|
||||
.set_canon_mode()
|
||||
.expect("failed to restore terminal mode");
|
||||
}
|
||||
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
@@ -465,7 +444,7 @@ impl Vmm {
|
||||
Ok(signals) => {
|
||||
self.signals = Some(signals.handle());
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(Error::EventFdClone)?;
|
||||
let original_termios_opt = Arc::clone(&self.original_termios_opt);
|
||||
let on_tty = Arc::clone(&self.on_tty);
|
||||
|
||||
let signal_handler_seccomp_filter = get_seccomp_filter(
|
||||
&self.seccomp_action,
|
||||
@@ -487,7 +466,7 @@ impl Vmm {
|
||||
}
|
||||
}
|
||||
std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
Vmm::signal_handler(signals, original_termios_opt, &exit_evt);
|
||||
Vmm::signal_handler(signals, on_tty, &exit_evt);
|
||||
}))
|
||||
.map_err(|_| {
|
||||
error!("vmm signal_handler thread panicked");
|
||||
@@ -504,7 +483,7 @@ impl Vmm {
|
||||
}
|
||||
|
||||
fn new(
|
||||
vmm_version: VmmVersionInfo,
|
||||
vmm_version: String,
|
||||
api_evt: EventFd,
|
||||
#[cfg(feature = "guest_debug")] debug_evt: EventFd,
|
||||
#[cfg(feature = "guest_debug")] vm_debug_evt: EventFd,
|
||||
@@ -554,7 +533,7 @@ impl Vmm {
|
||||
activate_evt,
|
||||
signals: None,
|
||||
threads: vec![],
|
||||
original_termios_opt: Arc::new(Mutex::new(None)),
|
||||
on_tty: Arc::new(AtomicBool::new(false)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -605,7 +584,7 @@ impl Vmm {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Arc::clone(&self.on_tty),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@@ -704,7 +683,7 @@ impl Vmm {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Arc::clone(&self.on_tty),
|
||||
Some(snapshot),
|
||||
Some(source_url),
|
||||
Some(restore_cfg.prefault),
|
||||
@@ -785,7 +764,7 @@ impl Vmm {
|
||||
serial_pty,
|
||||
console_pty,
|
||||
console_resize_pipe,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Arc::clone(&self.on_tty),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@@ -828,15 +807,8 @@ impl Vmm {
|
||||
}
|
||||
|
||||
fn vmm_ping(&self) -> VmmPingResponse {
|
||||
let VmmVersionInfo {
|
||||
build_version,
|
||||
version,
|
||||
} = self.version.clone();
|
||||
|
||||
VmmPingResponse {
|
||||
build_version,
|
||||
version,
|
||||
pid: std::process::id() as i64,
|
||||
version: self.version.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1295,7 +1267,7 @@ impl Vmm {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Arc::clone(&self.on_tty),
|
||||
Some(snapshot),
|
||||
)
|
||||
.map_err(|e| {
|
||||
@@ -2091,7 +2063,7 @@ mod unit_tests {
|
||||
|
||||
fn create_dummy_vmm() -> Vmm {
|
||||
Vmm::new(
|
||||
VmmVersionInfo::new("dummy", "dummy"),
|
||||
"dummy".to_string(),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
#[cfg(feature = "guest_debug")]
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::coredump::{
|
||||
use crate::migration::url_to_path;
|
||||
use crate::MEMORY_MANAGER_SNAPSHOT_ID;
|
||||
use crate::{GuestMemoryMmap, GuestRegionMmap};
|
||||
use acpi_tables::{aml, Aml};
|
||||
use acpi_tables::{aml, aml::Aml};
|
||||
use anyhow::anyhow;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
|
||||
@@ -31,7 +31,7 @@ use std::convert::TryInto;
|
||||
use std::ffi;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, Read};
|
||||
use std::ops::{BitAnd, Deref, Not, Sub};
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
@@ -327,15 +327,6 @@ pub enum Error {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
/// Failed to create UEFI flash
|
||||
CreateUefiFlash(HypervisorVmError),
|
||||
|
||||
/// Using a directory as a backing file for memory is not supported
|
||||
DirectoryAsBackingFileForMemory,
|
||||
|
||||
/// Failed to stat filesystem
|
||||
GetFileSystemBlockSize(io::Error),
|
||||
|
||||
/// Memory size is misaligned with default page size or its hugepage size
|
||||
MisalignedMemorySize,
|
||||
}
|
||||
|
||||
const ENABLE_FLAG: usize = 0;
|
||||
@@ -359,77 +350,6 @@ fn mmio_address_space_size(phys_bits: u8) -> u64 {
|
||||
(1 << phys_bits) - (1 << 16)
|
||||
}
|
||||
|
||||
// The `statfs` function can get information of hugetlbfs, and the hugepage size is in the
|
||||
// `f_bsize` field.
|
||||
//
|
||||
// See: https://github.com/torvalds/linux/blob/v6.3/fs/hugetlbfs/inode.c#L1169
|
||||
fn statfs_get_bsize(path: &str) -> Result<u64, Error> {
|
||||
let path = std::ffi::CString::new(path).map_err(|_| Error::InvalidMemoryParameters)?;
|
||||
let mut buf = std::mem::MaybeUninit::<libc::statfs>::uninit();
|
||||
|
||||
// SAFETY: FFI call with a valid path and buffer
|
||||
let ret = unsafe { libc::statfs(path.as_ptr(), buf.as_mut_ptr()) };
|
||||
if ret != 0 {
|
||||
return Err(Error::GetFileSystemBlockSize(
|
||||
std::io::Error::last_os_error(),
|
||||
));
|
||||
}
|
||||
|
||||
// SAFETY: `buf` is valid at this point
|
||||
// Because this value is always positive, just convert it directly.
|
||||
// Note that the `f_bsize` is `i64` in glibc and `u64` in musl, using `as u64` will be warned
|
||||
// by `clippy` on musl target. To avoid the warning, there should be `as _` instead of
|
||||
// `as u64`.
|
||||
let bsize = unsafe { (*buf.as_ptr()).f_bsize } as _;
|
||||
Ok(bsize)
|
||||
}
|
||||
|
||||
fn memory_zone_get_align_size(zone: &MemoryZoneConfig) -> Result<u64, Error> {
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u64 };
|
||||
|
||||
// There is no backend file and the `hugepages` is disabled, just use system page size.
|
||||
if zone.file.is_none() && !zone.hugepages {
|
||||
return Ok(page_size);
|
||||
}
|
||||
|
||||
// The `hugepages` is enabled and the `hugepage_size` is specified, just use it directly.
|
||||
if zone.hugepages && zone.hugepage_size.is_some() {
|
||||
return Ok(zone.hugepage_size.unwrap());
|
||||
}
|
||||
|
||||
// There are two scenarios here:
|
||||
// - `hugepages` is enabled but `hugepage_size` is not specified:
|
||||
// Call `statfs` for `/dev/hugepages` for getting the default size of hugepage
|
||||
// - The backing file is specified:
|
||||
// Call `statfs` for the file and get its `f_bsize`. If the value is larger than the page
|
||||
// size of normal page, just use the `f_bsize` because the file is in a hugetlbfs. If the
|
||||
// value is less than or equal to the page size, just use the page size.
|
||||
let path = zone.file.as_ref().map_or(Ok("/dev/hugepages"), |pathbuf| {
|
||||
pathbuf.to_str().ok_or(Error::InvalidMemoryParameters)
|
||||
})?;
|
||||
|
||||
let align_size = std::cmp::max(page_size, statfs_get_bsize(path)?);
|
||||
|
||||
Ok(align_size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn align_down<T>(val: T, align: T) -> T
|
||||
where
|
||||
T: BitAnd<Output = T> + Not<Output = T> + Sub<Output = T> + From<u8>,
|
||||
{
|
||||
val & !(align - 1u8.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_aligned<T>(val: T, align: T) -> bool
|
||||
where
|
||||
T: BitAnd<Output = T> + Sub<Output = T> + From<u8> + PartialEq,
|
||||
{
|
||||
(val & (align - 1u8.into())) == 0u8.into()
|
||||
}
|
||||
|
||||
impl BusDevice for MemoryManager {
|
||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||
if self.selected_slot < self.hotplug_slots.len() {
|
||||
@@ -519,9 +439,6 @@ impl MemoryManager {
|
||||
/// - First one mapping entirely the first memory zone on 0-1G range
|
||||
/// - Second one mapping partially the second memory zone on 1G-3G range
|
||||
/// - Third one mapping partially the second memory zone on 4G-6G range
|
||||
/// Also, all memory regions are page-size aligned (e.g. their sizes must
|
||||
/// be multiple of page-size), which may leave an additional hole in the
|
||||
/// address space when hugepage is used.
|
||||
fn create_memory_regions_from_zones(
|
||||
ram_regions: &[(GuestAddress, usize)],
|
||||
zones: &[MemoryZoneConfig],
|
||||
@@ -531,14 +448,9 @@ impl MemoryManager {
|
||||
let mut zones = zones.to_owned();
|
||||
let mut mem_regions = Vec::new();
|
||||
let mut zone = zones.remove(0);
|
||||
let mut zone_align_size = memory_zone_get_align_size(&zone)?;
|
||||
let mut zone_offset = 0u64;
|
||||
let mut zone_offset = 0;
|
||||
let mut memory_zones = HashMap::new();
|
||||
|
||||
if !is_aligned(zone.size, zone_align_size) {
|
||||
return Err(Error::MisalignedMemorySize);
|
||||
}
|
||||
|
||||
// Add zone id to the list of memory zones.
|
||||
memory_zones.insert(zone.id.clone(), MemoryZone::default());
|
||||
|
||||
@@ -550,20 +462,16 @@ impl MemoryManager {
|
||||
let mut ram_region_consumed = false;
|
||||
let mut pull_next_zone = false;
|
||||
|
||||
let ram_region_available_size =
|
||||
align_down(ram_region.1 as u64 - ram_region_offset, zone_align_size);
|
||||
if ram_region_available_size == 0 {
|
||||
break;
|
||||
}
|
||||
let zone_sub_size = zone.size - zone_offset;
|
||||
let ram_region_sub_size = ram_region.1 - ram_region_offset;
|
||||
let zone_sub_size = zone.size as usize - zone_offset;
|
||||
|
||||
let file_offset = zone_offset;
|
||||
let file_offset = zone_offset as u64;
|
||||
let region_start = ram_region
|
||||
.0
|
||||
.checked_add(ram_region_offset)
|
||||
.checked_add(ram_region_offset as u64)
|
||||
.ok_or(Error::GuestAddressOverFlow)?;
|
||||
let region_size = if zone_sub_size <= ram_region_available_size {
|
||||
if zone_sub_size == ram_region_available_size {
|
||||
let region_size = if zone_sub_size <= ram_region_sub_size {
|
||||
if zone_sub_size == ram_region_sub_size {
|
||||
ram_region_consumed = true;
|
||||
}
|
||||
|
||||
@@ -572,24 +480,21 @@ impl MemoryManager {
|
||||
|
||||
zone_sub_size
|
||||
} else {
|
||||
zone_offset += ram_region_available_size;
|
||||
zone_offset += ram_region_sub_size;
|
||||
ram_region_consumed = true;
|
||||
|
||||
ram_region_available_size
|
||||
ram_region_sub_size
|
||||
};
|
||||
|
||||
info!(
|
||||
"create ram region for zone {}, region_start: {:#x}, region_size: {:#x}",
|
||||
zone.id,
|
||||
region_start.raw_value(),
|
||||
region_size
|
||||
);
|
||||
let region = MemoryManager::create_ram_region(
|
||||
&zone.file,
|
||||
file_offset,
|
||||
region_start,
|
||||
region_size as usize,
|
||||
prefault.unwrap_or(zone.prefault),
|
||||
region_size,
|
||||
match prefault {
|
||||
Some(pf) => pf,
|
||||
None => zone.prefault,
|
||||
},
|
||||
zone.shared,
|
||||
zone.hugepages,
|
||||
zone.hugepage_size,
|
||||
@@ -614,10 +519,6 @@ impl MemoryManager {
|
||||
break;
|
||||
}
|
||||
zone = zones.remove(0);
|
||||
zone_align_size = memory_zone_get_align_size(&zone)?;
|
||||
if !is_aligned(zone.size, zone_align_size) {
|
||||
return Err(Error::MisalignedMemorySize);
|
||||
}
|
||||
|
||||
// Check if zone id already exist. In case it does, throw
|
||||
// an error as we need unique identifiers. Otherwise, add
|
||||
@@ -669,7 +570,10 @@ impl MemoryManager {
|
||||
guest_ram_mapping.file_offset,
|
||||
GuestAddress(guest_ram_mapping.gpa),
|
||||
guest_ram_mapping.size as usize,
|
||||
prefault.unwrap_or(zone_config.prefault),
|
||||
match prefault {
|
||||
Some(pf) => pf,
|
||||
None => zone_config.prefault,
|
||||
},
|
||||
zone_config.shared,
|
||||
zone_config.hugepages,
|
||||
zone_config.hugepage_size,
|
||||
@@ -1032,7 +936,7 @@ impl MemoryManager {
|
||||
)
|
||||
} else {
|
||||
// Init guest memory
|
||||
let arch_mem_regions = arch::arch_memory_regions();
|
||||
let arch_mem_regions = arch::arch_memory_regions(ram_size);
|
||||
|
||||
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
|
||||
.iter()
|
||||
@@ -1090,7 +994,10 @@ impl MemoryManager {
|
||||
0,
|
||||
start_addr,
|
||||
hotplug_size as usize,
|
||||
prefault.unwrap_or(zone.prefault),
|
||||
match prefault {
|
||||
Some(pf) => pf,
|
||||
None => zone.prefault,
|
||||
},
|
||||
zone.shared,
|
||||
zone.hugepages,
|
||||
zone.hugepage_size,
|
||||
@@ -1364,9 +1271,37 @@ impl MemoryManager {
|
||||
Ok(FileOffset::new(f, 0))
|
||||
}
|
||||
|
||||
fn open_backing_file(backing_file: &PathBuf, file_offset: u64) -> Result<FileOffset, Error> {
|
||||
fn open_backing_file(
|
||||
backing_file: &PathBuf,
|
||||
file_offset: u64,
|
||||
size: usize,
|
||||
) -> Result<FileOffset, Error> {
|
||||
if backing_file.is_dir() {
|
||||
Err(Error::DirectoryAsBackingFileForMemory)
|
||||
warn!(
|
||||
"Using a directory as a backing file for memory is deprecated \
|
||||
and will be removed in a future release. (See #5082)"
|
||||
);
|
||||
// Override file offset as it does not apply in this case.
|
||||
info!(
|
||||
"Ignoring file offset since the backing file is a \
|
||||
temporary file created from the specified directory."
|
||||
);
|
||||
let fs_str = format!("{}{}", backing_file.display(), "/tmpfile_XXXXXX");
|
||||
let fs = ffi::CString::new(fs_str).unwrap();
|
||||
let mut path = fs.as_bytes_with_nul().to_owned();
|
||||
let path_ptr = path.as_mut_ptr() as *mut _;
|
||||
// SAFETY: FFI call
|
||||
let fd = unsafe { libc::mkstemp(path_ptr) };
|
||||
if fd == -1 {
|
||||
return Err(Error::SharedFileCreate(std::io::Error::last_os_error()));
|
||||
}
|
||||
// SAFETY: FFI call
|
||||
unsafe { libc::unlink(path_ptr) };
|
||||
// SAFETY: fd is valid
|
||||
let f = unsafe { File::from_raw_fd(fd) };
|
||||
f.set_len(size as u64).map_err(Error::SharedFileSetLen)?;
|
||||
|
||||
Ok(FileOffset::new(f, 0))
|
||||
} else {
|
||||
let f = OpenOptions::new()
|
||||
.read(true)
|
||||
@@ -1406,7 +1341,7 @@ impl MemoryManager {
|
||||
} else {
|
||||
mmap_flags |= libc::MAP_PRIVATE;
|
||||
}
|
||||
Some(Self::open_backing_file(backing_file, file_offset)?)
|
||||
Some(Self::open_backing_file(backing_file, file_offset, size)?)
|
||||
} else if shared || hugepages {
|
||||
// For hugepages we must also MAP_SHARED otherwise we will trigger #4805
|
||||
// because the MAP_PRIVATE will trigger CoW against the backing file with
|
||||
@@ -1591,7 +1526,7 @@ impl MemoryManager {
|
||||
.ok_or(Error::MemoryRangeAllocation)?;
|
||||
|
||||
// Update the slot so that it can be queried via the I/O port
|
||||
let slot = &mut self.hotplug_slots[self.next_hotplug_slot];
|
||||
let mut slot = &mut self.hotplug_slots[self.next_hotplug_slot];
|
||||
slot.active = true;
|
||||
slot.inserting = true;
|
||||
slot.base = region.start_addr().0;
|
||||
@@ -2159,13 +2094,13 @@ struct MemoryNotify {
|
||||
}
|
||||
|
||||
impl Aml for MemoryNotify {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let object = aml::Path::new(&format!("M{:03}", self.slot_id));
|
||||
aml::If::new(
|
||||
&aml::Equal::new(&aml::Arg(0), &self.slot_id),
|
||||
vec![&aml::Notify::new(&object, &aml::Arg(1))],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2174,11 +2109,11 @@ struct MemorySlot {
|
||||
}
|
||||
|
||||
impl Aml for MemorySlot {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
aml::Device::new(
|
||||
format!("M{:03}", self.slot_id).as_str().into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0C80")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0C80")),
|
||||
&aml::Name::new("_UID".into(), &self.slot_id),
|
||||
/*
|
||||
_STA return value:
|
||||
@@ -2212,7 +2147,7 @@ impl Aml for MemorySlot {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2221,9 +2156,9 @@ struct MemorySlots {
|
||||
}
|
||||
|
||||
impl Aml for MemorySlots {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
for slot_id in 0..self.slots {
|
||||
MemorySlot { slot_id }.to_aml_bytes(sink);
|
||||
MemorySlot { slot_id }.append_aml_bytes(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2233,19 +2168,19 @@ struct MemoryMethods {
|
||||
}
|
||||
|
||||
impl Aml for MemoryMethods {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
// Add "MTFY" notification method
|
||||
let mut memory_notifies = Vec::new();
|
||||
for slot_id in 0..self.slots {
|
||||
memory_notifies.push(MemoryNotify { slot_id });
|
||||
}
|
||||
|
||||
let mut memory_notifies_refs: Vec<&dyn Aml> = Vec::new();
|
||||
let mut memory_notifies_refs: Vec<&dyn aml::Aml> = Vec::new();
|
||||
for memory_notifier in memory_notifies.iter() {
|
||||
memory_notifies_refs.push(memory_notifier);
|
||||
}
|
||||
|
||||
aml::Method::new("MTFY".into(), 2, true, memory_notifies_refs).to_aml_bytes(sink);
|
||||
aml::Method::new("MTFY".into(), 2, true, memory_notifies_refs).append_aml_bytes(bytes);
|
||||
|
||||
// MSCN method
|
||||
aml::Method::new(
|
||||
@@ -2291,7 +2226,7 @@ impl Aml for MemoryMethods {
|
||||
&aml::Release::new("MLCK".into()),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
// Memory status method
|
||||
aml::Method::new(
|
||||
@@ -2315,7 +2250,7 @@ impl Aml for MemoryMethods {
|
||||
&aml::Return::new(&aml::Local(0)),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
|
||||
// Memory range method
|
||||
aml::Method::new(
|
||||
@@ -2336,36 +2271,12 @@ impl Aml for MemoryMethods {
|
||||
0xFFFF_FFFF_FFFF_FFFEu64,
|
||||
)]),
|
||||
),
|
||||
&aml::CreateQWordField::new(
|
||||
&aml::Path::new("MINL"),
|
||||
&aml::Path::new("MR64"),
|
||||
&14usize,
|
||||
),
|
||||
&aml::CreateDWordField::new(
|
||||
&aml::Path::new("MINH"),
|
||||
&aml::Path::new("MR64"),
|
||||
&18usize,
|
||||
),
|
||||
&aml::CreateQWordField::new(
|
||||
&aml::Path::new("MAXL"),
|
||||
&aml::Path::new("MR64"),
|
||||
&22usize,
|
||||
),
|
||||
&aml::CreateDWordField::new(
|
||||
&aml::Path::new("MAXH"),
|
||||
&aml::Path::new("MR64"),
|
||||
&26usize,
|
||||
),
|
||||
&aml::CreateQWordField::new(
|
||||
&aml::Path::new("LENL"),
|
||||
&aml::Path::new("MR64"),
|
||||
&38usize,
|
||||
),
|
||||
&aml::CreateDWordField::new(
|
||||
&aml::Path::new("LENH"),
|
||||
&aml::Path::new("MR64"),
|
||||
&42usize,
|
||||
),
|
||||
&aml::CreateField::<u64>::new(&aml::Path::new("MR64"), &14usize, "MINL".into()),
|
||||
&aml::CreateField::<u32>::new(&aml::Path::new("MR64"), &18usize, "MINH".into()),
|
||||
&aml::CreateField::<u64>::new(&aml::Path::new("MR64"), &22usize, "MAXL".into()),
|
||||
&aml::CreateField::<u32>::new(&aml::Path::new("MR64"), &26usize, "MAXH".into()),
|
||||
&aml::CreateField::<u64>::new(&aml::Path::new("MR64"), &38usize, "LENL".into()),
|
||||
&aml::CreateField::<u32>::new(&aml::Path::new("MR64"), &42usize, "LENH".into()),
|
||||
&aml::Store::new(&aml::Path::new("MINL"), &aml::Path::new("\\_SB_.MHPC.MHBL")),
|
||||
&aml::Store::new(&aml::Path::new("MINH"), &aml::Path::new("\\_SB_.MHPC.MHBH")),
|
||||
&aml::Store::new(&aml::Path::new("LENL"), &aml::Path::new("\\_SB_.MHPC.MHLL")),
|
||||
@@ -2394,18 +2305,18 @@ impl Aml for MemoryMethods {
|
||||
&aml::Return::new(&aml::Path::new("MR64")),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Aml for MemoryManager {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
if let Some(acpi_address) = self.acpi_address {
|
||||
// Memory Hotplug Controller
|
||||
aml::Device::new(
|
||||
"_SB_.MHPC".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
||||
&aml::Name::new("_UID".into(), &"Memory Hotplug Controller"),
|
||||
// Mutex to protect concurrent access as we write to choose slot and then read back status
|
||||
&aml::Mutex::new("MLCK".into(), 0),
|
||||
@@ -2422,13 +2333,12 @@ impl Aml for MemoryManager {
|
||||
&aml::OpRegion::new(
|
||||
"MHPR".into(),
|
||||
aml::OpRegionSpace::SystemMemory,
|
||||
&(acpi_address.0 as usize),
|
||||
&MEMORY_MANAGER_ACPI_SIZE,
|
||||
acpi_address.0 as usize,
|
||||
MEMORY_MANAGER_ACPI_SIZE,
|
||||
),
|
||||
&aml::Field::new(
|
||||
"MHPR".into(),
|
||||
aml::FieldAccessType::DWord,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::Preserve,
|
||||
vec![
|
||||
aml::FieldEntry::Named(*b"MHBL", 32), // Base (low 4 bytes)
|
||||
@@ -2440,7 +2350,6 @@ impl Aml for MemoryManager {
|
||||
&aml::Field::new(
|
||||
"MHPR".into(),
|
||||
aml::FieldAccessType::DWord,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::Preserve,
|
||||
vec![
|
||||
aml::FieldEntry::Reserved(128),
|
||||
@@ -2450,7 +2359,6 @@ impl Aml for MemoryManager {
|
||||
&aml::Field::new(
|
||||
"MHPR".into(),
|
||||
aml::FieldAccessType::Byte,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::WriteAsZeroes,
|
||||
vec![
|
||||
aml::FieldEntry::Reserved(160),
|
||||
@@ -2463,7 +2371,6 @@ impl Aml for MemoryManager {
|
||||
&aml::Field::new(
|
||||
"MHPR".into(),
|
||||
aml::FieldAccessType::DWord,
|
||||
aml::FieldLockRule::NoLock,
|
||||
aml::FieldUpdateRule::Preserve,
|
||||
vec![
|
||||
aml::FieldEntry::Named(*b"MSEL", 32), // Selector
|
||||
@@ -2479,18 +2386,18 @@ impl Aml for MemoryManager {
|
||||
},
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
} else {
|
||||
aml::Device::new(
|
||||
"_SB_.MHPC".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
|
||||
&aml::Name::new("_UID".into(), &"Memory Hotplug Controller"),
|
||||
// Empty MSCN for GED
|
||||
&aml::Method::new("MSCN".into(), 0, true, vec![]),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -2502,7 +2409,7 @@ impl Aml for MemoryManager {
|
||||
aml::Device::new(
|
||||
"_SB_.EPC_".into(),
|
||||
vec![
|
||||
&aml::Name::new("_HID".into(), &aml::EISAName::new("INT0E0C")),
|
||||
&aml::Name::new("_HID".into(), &aml::EisaName::new("INT0E0C")),
|
||||
// QWORD describing the EPC region start and size
|
||||
&aml::Name::new(
|
||||
"_CRS".into(),
|
||||
@@ -2516,7 +2423,7 @@ impl Aml for MemoryManager {
|
||||
&aml::Method::new("_STA".into(), 0, false, vec![&aml::Return::new(&0xfu8)]),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
//
|
||||
|
||||
use crate::device_manager::{AddressManager, DeviceManagerError, DeviceManagerResult};
|
||||
use acpi_tables::{self, aml, Aml};
|
||||
use acpi_tables::aml::{self, Aml};
|
||||
use arch::layout;
|
||||
use pci::{DeviceRelocation, PciBdf, PciBus, PciConfigMmio, PciRoot};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -171,7 +171,7 @@ struct PciDevSlot {
|
||||
}
|
||||
|
||||
impl Aml for PciDevSlot {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let sun = self.device_id;
|
||||
let adr: u32 = (self.device_id as u32) << 16;
|
||||
aml::Device::new(
|
||||
@@ -190,7 +190,7 @@ impl Aml for PciDevSlot {
|
||||
),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,33 +199,33 @@ struct PciDevSlotNotify {
|
||||
}
|
||||
|
||||
impl Aml for PciDevSlotNotify {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let device_id_mask: u32 = 1 << self.device_id;
|
||||
let object = aml::Path::new(&format!("S{:03}", self.device_id));
|
||||
aml::And::new(&aml::Local(0), &aml::Arg(0), &device_id_mask).to_aml_bytes(sink);
|
||||
aml::And::new(&aml::Local(0), &aml::Arg(0), &device_id_mask).append_aml_bytes(bytes);
|
||||
aml::If::new(
|
||||
&aml::Equal::new(&aml::Local(0), &device_id_mask),
|
||||
vec![&aml::Notify::new(&object, &aml::Arg(1))],
|
||||
)
|
||||
.to_aml_bytes(sink);
|
||||
.append_aml_bytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
struct PciDevSlotMethods {}
|
||||
|
||||
impl Aml for PciDevSlotMethods {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let mut device_notifies = Vec::new();
|
||||
for device_id in 0..32 {
|
||||
device_notifies.push(PciDevSlotNotify { device_id });
|
||||
}
|
||||
|
||||
let mut device_notifies_refs: Vec<&dyn Aml> = Vec::new();
|
||||
let mut device_notifies_refs: Vec<&dyn aml::Aml> = Vec::new();
|
||||
for device_notify in device_notifies.iter() {
|
||||
device_notifies_refs.push(device_notify);
|
||||
}
|
||||
|
||||
aml::Method::new("DVNT".into(), 2, true, device_notifies_refs).to_aml_bytes(sink);
|
||||
aml::Method::new("DVNT".into(), 2, true, device_notifies_refs).append_aml_bytes(bytes);
|
||||
aml::Method::new(
|
||||
"PCNT".into(),
|
||||
0,
|
||||
@@ -244,14 +244,14 @@ impl Aml for PciDevSlotMethods {
|
||||
&aml::Release::new("\\_SB_.PHPR.BLCK".into()),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
struct PciDsmMethod {}
|
||||
|
||||
impl Aml for PciDsmMethod {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
// Refer to ACPI spec v6.3 Ch 9.1.1 and PCI Firmware spec v3.3 Ch 4.6.1
|
||||
// _DSM (Device Specific Method), the following is the implementation in ASL.
|
||||
/*
|
||||
@@ -292,11 +292,11 @@ impl Aml for PciDsmMethod {
|
||||
false,
|
||||
vec![
|
||||
&aml::If::new(
|
||||
&aml::Equal::new(&aml::Arg(0), &aml::BufferData::new(uuid_buf)),
|
||||
&aml::Equal::new(&aml::Arg(0), &aml::Buffer::new(uuid_buf)),
|
||||
vec![
|
||||
&aml::If::new(
|
||||
&aml::Equal::new(&aml::Arg(2), &aml::ZERO),
|
||||
vec![&aml::Return::new(&aml::BufferData::new(vec![0x21]))],
|
||||
vec![&aml::Return::new(&aml::Buffer::new(vec![0x21]))],
|
||||
),
|
||||
&aml::If::new(
|
||||
&aml::Equal::new(&aml::Arg(2), &0x05u8),
|
||||
@@ -304,19 +304,19 @@ impl Aml for PciDsmMethod {
|
||||
),
|
||||
],
|
||||
),
|
||||
&aml::Return::new(&aml::BufferData::new(vec![0])),
|
||||
&aml::Return::new(&aml::Buffer::new(vec![0])),
|
||||
],
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Aml for PciSegment {
|
||||
fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) {
|
||||
let mut pci_dsdt_inner_data: Vec<&dyn Aml> = Vec::new();
|
||||
let hid = aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A08"));
|
||||
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
|
||||
let mut pci_dsdt_inner_data: Vec<&dyn aml::Aml> = Vec::new();
|
||||
let hid = aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A08"));
|
||||
pci_dsdt_inner_data.push(&hid);
|
||||
let cid = aml::Name::new("_CID".into(), &aml::EISAName::new("PNP0A03"));
|
||||
let cid = aml::Name::new("_CID".into(), &aml::EisaName::new("PNP0A03"));
|
||||
pci_dsdt_inner_data.push(&cid);
|
||||
let adr = aml::Name::new("_ADR".into(), &aml::ZERO);
|
||||
pci_dsdt_inner_data.push(&adr);
|
||||
@@ -346,7 +346,7 @@ impl Aml for PciSegment {
|
||||
&aml::ResourceTemplate::new(vec![
|
||||
&aml::AddressSpace::new_bus_number(0x0u16, 0x0u16),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&aml::IO::new(0xcf8, 0xcf8, 1, 0x8),
|
||||
&aml::Io::new(0xcf8, 0xcf8, 1, 0x8),
|
||||
&aml::AddressSpace::new_memory(
|
||||
aml::AddressSpaceCachable::NotCacheable,
|
||||
true,
|
||||
@@ -418,9 +418,9 @@ impl Aml for PciSegment {
|
||||
pci_dsdt_inner_data.push(&prt);
|
||||
|
||||
aml::Device::new(
|
||||
format!("_SB_.PC{:02X}", self.id).as_str().into(),
|
||||
format!("_SB_.PCI{:X}", self.id).as_str().into(),
|
||||
pci_dsdt_inner_data,
|
||||
)
|
||||
.to_aml_bytes(sink)
|
||||
.append_aml_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ macro_rules! or {
|
||||
const TCGETS: u64 = 0x5401;
|
||||
const TCSETS: u64 = 0x5402;
|
||||
const TIOCSCTTY: u64 = 0x540E;
|
||||
const TIOCGPGRP: u64 = 0x540F;
|
||||
const TIOCSPGRP: u64 = 0x5410;
|
||||
const TIOCGWINSZ: u64 = 0x5413;
|
||||
const TIOCSPTLCK: u64 = 0x4004_5431;
|
||||
@@ -168,7 +167,6 @@ mod mshv {
|
||||
pub const MSHV_GET_GPA_ACCESS_STATES: u64 = 0xc01c_b812;
|
||||
pub const MSHV_VP_TRANSLATE_GVA: u64 = 0xc020_b80e;
|
||||
pub const MSHV_CREATE_PARTITION: u64 = 0x4030_b801;
|
||||
pub const MSHV_VP_REGISTER_INTERCEPT_RESULT: u64 = 0x4030_b817;
|
||||
}
|
||||
#[cfg(feature = "mshv")]
|
||||
use mshv::*;
|
||||
@@ -198,12 +196,6 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_GET_GPA_ACCESS_STATES)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_VP_TRANSLATE_GVA)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, MSHV_CREATE_PARTITION)?],
|
||||
and![Cond::new(
|
||||
1,
|
||||
ArgLen::Dword,
|
||||
Eq,
|
||||
MSHV_VP_REGISTER_INTERCEPT_RESULT
|
||||
)?],
|
||||
])
|
||||
}
|
||||
|
||||
@@ -272,7 +264,6 @@ fn create_vmm_ioctl_seccomp_rule_common(
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, SIOCSIFNETMASK)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TCSETS)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TCGETS)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCGPGRP)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCGTPEER)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCGWINSZ)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCSCTTY)?],
|
||||
@@ -464,7 +455,6 @@ fn signal_handler_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, Backend
|
||||
|
||||
fn create_pty_foreground_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, BackendError> {
|
||||
Ok(or![
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCGPGRP)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCSCTTY)?],
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, TIOCSPGRP)?],
|
||||
])
|
||||
@@ -484,7 +474,6 @@ fn pty_foreground_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, Backend
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
(libc::SYS_ppoll, vec![]),
|
||||
(libc::SYS_read, vec![]),
|
||||
(libc::SYS_restart_syscall, vec![]),
|
||||
(libc::SYS_rt_sigaction, vec![]),
|
||||
(libc::SYS_rt_sigreturn, vec![]),
|
||||
(libc::SYS_setsid, vec![]),
|
||||
@@ -509,7 +498,6 @@ fn vmm_thread_rules(
|
||||
(libc::SYS_clone, vec![]),
|
||||
(libc::SYS_clone3, vec![]),
|
||||
(libc::SYS_close, vec![]),
|
||||
(libc::SYS_close_range, vec![]),
|
||||
(libc::SYS_connect, vec![]),
|
||||
(libc::SYS_dup, vec![]),
|
||||
(libc::SYS_epoll_create1, vec![]),
|
||||
@@ -531,7 +519,6 @@ fn vmm_thread_rules(
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
(libc::SYS_newfstatat, vec![]),
|
||||
(libc::SYS_futex, vec![]),
|
||||
(libc::SYS_getdents64, vec![]),
|
||||
(libc::SYS_getpgid, vec![]),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
(libc::SYS_getpgrp, vec![]),
|
||||
@@ -610,7 +597,6 @@ fn vmm_thread_rules(
|
||||
(libc::SYS_socketpair, vec![]),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
(libc::SYS_stat, vec![]),
|
||||
(libc::SYS_statfs, vec![]),
|
||||
(libc::SYS_statx, vec![]),
|
||||
(libc::SYS_tgkill, vec![]),
|
||||
(libc::SYS_timerfd_create, vec![]),
|
||||
@@ -717,7 +703,6 @@ fn vcpu_thread_rules(
|
||||
(libc::SYS_madvise, vec![]),
|
||||
(libc::SYS_mmap, vec![]),
|
||||
(libc::SYS_mprotect, vec![]),
|
||||
(libc::SYS_mremap, vec![]),
|
||||
(libc::SYS_munmap, vec![]),
|
||||
(libc::SYS_nanosleep, vec![]),
|
||||
(libc::SYS_newfstatat, vec![]),
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
// Copyright 2021, 2023 Alyssa Ross <hi@alyssa.is>
|
||||
// Copyright 2021 Alyssa Ross <hi@alyssa.is>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::clone3::{clone3, clone_args, CLONE_CLEAR_SIGHAND};
|
||||
use arch::_NSIG;
|
||||
use libc::{
|
||||
c_int, c_void, close, fork, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset,
|
||||
siginfo_t, signal, sigprocmask, syscall, tcgetpgrp, tcsetpgrp, SYS_close_range, EINVAL, ENOSYS,
|
||||
ENOTTY, O_CLOEXEC, POLLERR, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY,
|
||||
c_int, c_void, close, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset, siginfo_t,
|
||||
sigprocmask, tcsetpgrp, O_CLOEXEC, POLLERR, SIGWINCH, SIG_SETMASK, STDIN_FILENO, STDOUT_FILENO,
|
||||
TIOCSCTTY,
|
||||
};
|
||||
use seccompiler::{apply_filter, BpfProgram};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs::{read_dir, File};
|
||||
use std::fs::File;
|
||||
use std::io::{self, ErrorKind, Read, Write};
|
||||
use std::iter::once;
|
||||
use std::mem::size_of;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::prelude::*;
|
||||
@@ -63,107 +60,17 @@ fn unblock_all_signals() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller is responsible for ensuring all file descriptors not listed
|
||||
/// in `keep_fds` are not accessed after this point, and that no other
|
||||
/// thread is opening file descriptors while this function is
|
||||
/// running.
|
||||
unsafe fn close_fds_fallback(keep_fds: &BTreeSet<RawFd>) {
|
||||
// We collect these instead of iterating through them, because we
|
||||
// don't want to close the descriptor for /proc/self/fd while
|
||||
// we're iterating through it.
|
||||
let open_fds: BTreeSet<RawFd> = read_dir("/proc/self/fd")
|
||||
.unwrap()
|
||||
.map(Result::unwrap)
|
||||
.filter_map(|s| s.file_name().into_string().ok()?.parse().ok())
|
||||
.collect();
|
||||
|
||||
for fd in open_fds.difference(keep_fds) {
|
||||
close(*fd);
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller is responsible for ensuring all file descriptors not listed
|
||||
/// in `keep_fds` are not accessed after this point, and that no other
|
||||
/// thread is opening file descriptors while this function is
|
||||
/// running.
|
||||
unsafe fn close_unused_fds(keep_fds: &mut [RawFd]) {
|
||||
keep_fds.sort();
|
||||
|
||||
// Iterate over the gaps between descriptors we want to keep.
|
||||
let firsts = keep_fds.iter().map(|fd| fd + 1);
|
||||
for (i, first) in once(0).chain(firsts).enumerate() {
|
||||
// The next fd is the one at i, because the indexes in the
|
||||
// iterator are offset by one due to the initial 0.
|
||||
let next_keep_fd = keep_fds.get(i);
|
||||
let last = next_keep_fd.map(|fd| fd - 1).unwrap_or(RawFd::MAX);
|
||||
|
||||
if first > last {
|
||||
continue;
|
||||
}
|
||||
|
||||
if syscall(SYS_close_range, first, last, 0) == -1 {
|
||||
// The kernel might be too old to have close_range, in
|
||||
// which case we need to fall back to an uglier method.
|
||||
let e = io::Error::last_os_error();
|
||||
if e.raw_os_error() == Some(ENOSYS) {
|
||||
return close_fds_fallback(&keep_fds.iter().copied().collect());
|
||||
}
|
||||
|
||||
panic!("close_range: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_foreground_process_group(tty: &mut File) -> io::Result<()> {
|
||||
// SAFETY: trivially safe.
|
||||
let my_pgrp = unsafe { getpgrp() };
|
||||
// SAFETY: we have borrowed tty.
|
||||
let tty_pgrp = unsafe { tcgetpgrp(tty.as_raw_fd()) };
|
||||
|
||||
if tty_pgrp == -1 {
|
||||
let e = io::Error::last_os_error();
|
||||
if e.raw_os_error() != Some(ENOTTY) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
if tty_pgrp == my_pgrp {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// SAFETY: trivially safe.
|
||||
let my_pgrp = unsafe { setsid() };
|
||||
if my_pgrp == -1 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
// Set the tty to be this process's controlling terminal.
|
||||
// SAFETY: we have borrowed tty.
|
||||
if unsafe { ioctl(tty.as_raw_fd(), TIOCSCTTY, 0) } == -1 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
// Become the foreground process group of the tty.
|
||||
// SAFETY: we have borrowed tty.
|
||||
if unsafe { tcsetpgrp(tty.as_raw_fd(), my_pgrp) } == -1 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, mut tty: File) -> ! {
|
||||
// SAFETY: any references to these file descriptors are
|
||||
// unreachable, because this function never returns.
|
||||
unsafe {
|
||||
close_unused_fds(&mut [STDERR_FILENO, tx.as_raw_fd(), tty.as_raw_fd()]);
|
||||
}
|
||||
|
||||
fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, pty: File) -> ! {
|
||||
TX.with(|opt| opt.replace(Some(tx)));
|
||||
|
||||
let pty_fd = pty.into_raw_fd();
|
||||
|
||||
// SAFETY: FFI calls
|
||||
unsafe {
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
}
|
||||
|
||||
unblock_all_signals().unwrap();
|
||||
|
||||
if !seccomp_filter.is_empty() {
|
||||
@@ -172,8 +79,20 @@ fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, mut tty: File) -
|
||||
|
||||
register_signal_handler(SIGWINCH, sigwinch_handler).unwrap();
|
||||
|
||||
set_foreground_process_group(&mut tty).unwrap();
|
||||
drop(tty);
|
||||
// SAFETY: FFI calls
|
||||
unsafe {
|
||||
// Create a new session (and therefore a new process group).
|
||||
assert_ne!(setsid(), -1);
|
||||
|
||||
// Set the tty to be this process's controlling terminal.
|
||||
assert_ne!(ioctl(pty_fd, TIOCSCTTY, 0), -1);
|
||||
|
||||
// Become the foreground process group of the tty.
|
||||
assert_ne!(tcsetpgrp(pty_fd, getpgrp()), -1);
|
||||
|
||||
// Close the PTY fd
|
||||
assert_ne!(close(pty_fd), -1);
|
||||
}
|
||||
|
||||
notify();
|
||||
|
||||
@@ -200,36 +119,11 @@ fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, mut tty: File) -
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Same as [`fork`].
|
||||
unsafe fn clone_clear_sighand() -> io::Result<u64> {
|
||||
let mut args = clone_args::default();
|
||||
args.flags |= CLONE_CLEAR_SIGHAND;
|
||||
let r = clone3(&mut args, size_of::<clone_args>());
|
||||
if r != -1 {
|
||||
return Ok(r.try_into().unwrap());
|
||||
}
|
||||
let e = io::Error::last_os_error();
|
||||
if e.raw_os_error() != Some(ENOSYS) && e.raw_os_error() != Some(EINVAL) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// If CLONE_CLEAR_SIGHAND isn't available, fall back to resetting
|
||||
// all the signal handlers one by one.
|
||||
let r = fork();
|
||||
if r == -1 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
if r == 0 {
|
||||
for signum in 1.._NSIG {
|
||||
let _ = signal(signum, SIG_DFL);
|
||||
}
|
||||
}
|
||||
Ok(r.try_into().unwrap())
|
||||
}
|
||||
|
||||
pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io::Result<File> {
|
||||
pub fn start_sigwinch_listener(
|
||||
seccomp_filter: BpfProgram,
|
||||
pty_main: File,
|
||||
pty_sub: File,
|
||||
) -> io::Result<File> {
|
||||
let mut pipe = [-1; 2];
|
||||
// SAFETY: FFI call with valid arguments
|
||||
if unsafe { pipe2(pipe.as_mut_ptr(), O_CLOEXEC) } == -1 {
|
||||
@@ -241,9 +135,18 @@ pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io:
|
||||
// SAFETY: pipe[1] is valid
|
||||
let tx = unsafe { File::from_raw_fd(pipe[1]) };
|
||||
|
||||
let mut args = clone_args::default();
|
||||
args.flags |= CLONE_CLEAR_SIGHAND;
|
||||
|
||||
// SAFETY: FFI call
|
||||
if unsafe { clone_clear_sighand() }? == 0 {
|
||||
sigwinch_listener_main(seccomp_filter, tx, tty_sub);
|
||||
match unsafe { clone3(&mut args, size_of::<clone_args>()) } {
|
||||
-1 => return Err(io::Error::last_os_error()),
|
||||
0 => {
|
||||
drop(rx);
|
||||
drop(pty_main);
|
||||
sigwinch_listener_main(seccomp_filter, tx, pty_sub);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
drop(tx);
|
||||
|
||||
128
vmm/src/vm.rs
128
vmm/src/vm.rs
@@ -21,7 +21,7 @@ use crate::coredump::{
|
||||
CpuElf64Writable, DumpState, Elf64Writable, GuestDebuggable, GuestDebuggableError, NoteDescType,
|
||||
};
|
||||
use crate::cpu;
|
||||
use crate::device_manager::{DeviceManager, DeviceManagerError, PtyPair};
|
||||
use crate::device_manager::{Console, DeviceManager, DeviceManagerError, PtyPair};
|
||||
use crate::device_tree::DeviceTree;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload};
|
||||
@@ -33,6 +33,7 @@ use crate::migration::get_vm_snapshot;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use crate::migration::url_to_file;
|
||||
use crate::migration::{url_to_path, SNAPSHOT_CONFIG_FILE, SNAPSHOT_STATE_FILE};
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::{
|
||||
PciDeviceInfo, CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, MEMORY_MANAGER_SNAPSHOT_ID,
|
||||
@@ -55,7 +56,6 @@ use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs;
|
||||
use hypervisor::{HypervisorVmError, VmOps};
|
||||
use libc::{termios, SIGWINCH};
|
||||
use linux_loader::cmdline::Cmdline;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use linux_loader::elf;
|
||||
@@ -64,8 +64,9 @@ use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use linux_loader::loader::pe::Error::InvalidImageMagicNumber;
|
||||
use linux_loader::loader::KernelLoader;
|
||||
use seccompiler::SeccompAction;
|
||||
use seccompiler::{apply_filter, SeccompAction};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use signal_hook::{consts::SIGWINCH, iterator::backend::Handle, iterator::Signals};
|
||||
use std::cmp;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
@@ -79,6 +80,8 @@ use std::mem::size_of;
|
||||
use std::num::Wrapping;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::time::Instant;
|
||||
use std::{result, str, thread};
|
||||
@@ -94,6 +97,7 @@ use vm_migration::{
|
||||
SnapshotData, Snapshottable, Transportable,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::signal::unblock_signal;
|
||||
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
|
||||
|
||||
/// Errors associated with VM management
|
||||
@@ -314,10 +318,10 @@ impl VmState {
|
||||
fn valid_transition(self, new_state: VmState) -> Result<()> {
|
||||
match self {
|
||||
VmState::Created => match new_state {
|
||||
VmState::Created => Err(Error::InvalidStateTransition(self, new_state)),
|
||||
VmState::Running | VmState::Paused | VmState::BreakPoint | VmState::Shutdown => {
|
||||
Ok(())
|
||||
VmState::Created | VmState::Shutdown => {
|
||||
Err(Error::InvalidStateTransition(self, new_state))
|
||||
}
|
||||
VmState::Running | VmState::Paused | VmState::BreakPoint => Ok(()),
|
||||
},
|
||||
|
||||
VmState::Running => match new_state {
|
||||
@@ -430,6 +434,7 @@ pub struct Vm {
|
||||
threads: Vec<thread::JoinHandle<()>>,
|
||||
device_manager: Arc<Mutex<DeviceManager>>,
|
||||
config: Arc<Mutex<VmConfig>>,
|
||||
signals: Option<Handle>,
|
||||
state: RwLock<VmState>,
|
||||
cpu_manager: Arc<Mutex<cpu::CpuManager>>,
|
||||
memory_manager: Arc<Mutex<MemoryManager>>,
|
||||
@@ -439,7 +444,8 @@ pub struct Vm {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
saved_clock: Option<hypervisor::ClockData>,
|
||||
numa_nodes: NumaNodes,
|
||||
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
|
||||
seccomp_action: SeccompAction,
|
||||
exit_evt: EventFd,
|
||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
stop_on_boot: bool,
|
||||
load_payload_handle: Option<thread::JoinHandle<Result<EntryPoint>>>,
|
||||
@@ -463,7 +469,7 @@ impl Vm {
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios: Arc<Mutex<Option<termios>>>,
|
||||
on_tty: Arc<AtomicBool>,
|
||||
snapshot: Option<Snapshot>,
|
||||
) -> Result<Self> {
|
||||
trace_scoped!("Vm::new_from_memory_manager");
|
||||
@@ -585,12 +591,7 @@ impl Vm {
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.create_devices(
|
||||
serial_pty,
|
||||
console_pty,
|
||||
console_resize_pipe,
|
||||
original_termios,
|
||||
)
|
||||
.create_devices(serial_pty, console_pty, console_resize_pipe, on_tty)
|
||||
.map_err(Error::DeviceManager)?;
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
@@ -635,6 +636,7 @@ impl Vm {
|
||||
device_manager,
|
||||
config,
|
||||
threads: Vec::with_capacity(1),
|
||||
signals: None,
|
||||
state: RwLock::new(vm_state),
|
||||
cpu_manager,
|
||||
memory_manager,
|
||||
@@ -642,6 +644,8 @@ impl Vm {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
saved_clock,
|
||||
numa_nodes,
|
||||
seccomp_action: seccomp_action.clone(),
|
||||
exit_evt,
|
||||
hypervisor,
|
||||
stop_on_boot,
|
||||
load_payload_handle,
|
||||
@@ -740,7 +744,7 @@ impl Vm {
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios: Arc<Mutex<Option<termios>>>,
|
||||
on_tty: Arc<AtomicBool>,
|
||||
snapshot: Option<Snapshot>,
|
||||
source_url: Option<&str>,
|
||||
prefault: Option<bool>,
|
||||
@@ -810,7 +814,7 @@ impl Vm {
|
||||
serial_pty,
|
||||
console_pty,
|
||||
console_resize_pipe,
|
||||
original_termios,
|
||||
on_tty,
|
||||
snapshot,
|
||||
)
|
||||
}
|
||||
@@ -1201,6 +1205,11 @@ impl Vm {
|
||||
|
||||
state.valid_transition(new_state)?;
|
||||
|
||||
// Trigger the termination of the signal_handler thread
|
||||
if let Some(signals) = self.signals.take() {
|
||||
signals.close();
|
||||
}
|
||||
|
||||
// Wake up the DeviceManager threads so they will get terminated cleanly
|
||||
self.device_manager
|
||||
.lock()
|
||||
@@ -1258,7 +1267,7 @@ impl Vm {
|
||||
.resize(desired_memory)
|
||||
.map_err(Error::MemoryManager)?;
|
||||
|
||||
let memory_config = &mut self.config.lock().unwrap().memory;
|
||||
let mut memory_config = &mut self.config.lock().unwrap().memory;
|
||||
|
||||
if let Some(new_region) = &new_region {
|
||||
self.device_manager
|
||||
@@ -1606,6 +1615,18 @@ impl Vm {
|
||||
Ok(self.device_manager.lock().unwrap().counters())
|
||||
}
|
||||
|
||||
fn signal_handler(mut signals: Signals, console_input_clone: Arc<Console>) {
|
||||
for sig in &Vm::HANDLED_SIGNALS {
|
||||
unblock_signal(*sig).unwrap();
|
||||
}
|
||||
|
||||
for signal in signals.forever() {
|
||||
if signal == SIGWINCH {
|
||||
console_input_clone.update_console_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
fn extract_tdvf_sections(&mut self) -> Result<(Vec<TdvfSection>, bool)> {
|
||||
use arch::x86_64::tdx::*;
|
||||
@@ -1902,6 +1923,49 @@ impl Vm {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_signal_handler(&mut self) -> Result<()> {
|
||||
let console = self.device_manager.lock().unwrap().console().clone();
|
||||
let signals = Signals::new(Vm::HANDLED_SIGNALS);
|
||||
match signals {
|
||||
Ok(signals) => {
|
||||
self.signals = Some(signals.handle());
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(Error::EventFdClone)?;
|
||||
let signal_handler_seccomp_filter = get_seccomp_filter(
|
||||
&self.seccomp_action,
|
||||
Thread::SignalHandler,
|
||||
self.hypervisor.hypervisor_type(),
|
||||
)
|
||||
.map_err(Error::CreateSeccompFilter)?;
|
||||
self.threads.push(
|
||||
thread::Builder::new()
|
||||
.name("vm_signal_handler".to_string())
|
||||
.spawn(move || {
|
||||
if !signal_handler_seccomp_filter.is_empty() {
|
||||
if let Err(e) = apply_filter(&signal_handler_seccomp_filter)
|
||||
.map_err(Error::ApplySeccompFilter)
|
||||
{
|
||||
error!("Error applying seccomp filter: {:?}", e);
|
||||
exit_evt.write(1).ok();
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
Vm::signal_handler(signals, console);
|
||||
}))
|
||||
.map_err(|_| {
|
||||
error!("vm signal_handler thread panicked");
|
||||
exit_evt.write(1).ok()
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.map_err(Error::SignalHandlerSpawn)?,
|
||||
);
|
||||
}
|
||||
Err(e) => error!("Signal not found {}", e),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Creates ACPI tables
|
||||
// In case of TDX being used, this is a no-op since the tables will be
|
||||
// created and passed when populating the HOB.
|
||||
@@ -1955,6 +2019,8 @@ impl Vm {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let rsdp_addr = self.create_acpi_tables();
|
||||
|
||||
self.setup_signal_handler()?;
|
||||
|
||||
// Load kernel synchronously or if asynchronous then wait for load to
|
||||
// finish.
|
||||
let entry_point = self.entry_point()?;
|
||||
@@ -2004,18 +2070,6 @@ impl Vm {
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
// Note: For x86, always call this function before invoking start boot vcpus.
|
||||
// Otherwise guest would fail to boot because we haven't created the
|
||||
// userspace mappings to update the hypervisor about the memory mappings.
|
||||
// These mappings must be created before we start the vCPU threads for
|
||||
// the very first time.
|
||||
self.memory_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate_address_space()
|
||||
.map_err(Error::MemoryManager)?;
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
if let Some(hob_address) = hob_address {
|
||||
// With the HOB address extracted the vCPUs can have
|
||||
@@ -2033,6 +2087,18 @@ impl Vm {
|
||||
self.vm.tdx_finalize().map_err(Error::FinalizeTdx)?;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
// Note: For x86, always call this function before invoking start boot vcpus.
|
||||
// Otherwise guest would fail to boot because we haven't created the
|
||||
// userspace mappings to update the hypervisor about the memory mappings.
|
||||
// These mappings must be created before we start the vCPU threads for
|
||||
// the very first time.
|
||||
self.memory_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate_address_space()
|
||||
.map_err(Error::MemoryManager)?;
|
||||
|
||||
self.cpu_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
@@ -2067,6 +2133,8 @@ impl Vm {
|
||||
.start_restored_vcpus()
|
||||
.map_err(Error::CpuManager)?;
|
||||
|
||||
self.setup_signal_handler()?;
|
||||
|
||||
event!("vm", "restored");
|
||||
Ok(())
|
||||
}
|
||||
@@ -2694,7 +2762,7 @@ mod tests {
|
||||
// Check the transitions from Created
|
||||
assert!(state.valid_transition(VmState::Created).is_err());
|
||||
assert!(state.valid_transition(VmState::Running).is_ok());
|
||||
assert!(state.valid_transition(VmState::Shutdown).is_ok());
|
||||
assert!(state.valid_transition(VmState::Shutdown).is_err());
|
||||
assert!(state.valid_transition(VmState::Paused).is_ok());
|
||||
assert!(state.valid_transition(VmState::BreakPoint).is_ok());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user