Compare commits
61 Commits
0154559b0e
...
3599daf378
Author | SHA1 | Date |
---|---|---|
Praveen K Paladugu | 3599daf378 | |
Praveen K Paladugu | 2ba4bec97f | |
Praveen K Paladugu | 118870b122 | |
Praveen K Paladugu | 1585a06aca | |
Praveen K Paladugu | 32d2fb5023 | |
Praveen K Paladugu | 310a30bbcb | |
Rob Bradford | 7e25cc2aa0 | |
Rob Bradford | 8b86c7724b | |
Rob Bradford | ea23c16c5a | |
Rob Bradford | 3def18f502 | |
Rob Bradford | 2bf6f9300a | |
Rob Bradford | fd43b79f96 | |
dependabot[bot] | a70808bae9 | |
dependabot[bot] | 97d617f071 | |
dependabot[bot] | 0194a635f7 | |
dependabot[bot] | e5d0acf0a9 | |
Rob Bradford | 622a1a3735 | |
Rob Bradford | f5abb168e3 | |
dependabot[bot] | 1e3ef1a548 | |
dependabot[bot] | 275a63655b | |
dependabot[bot] | 16651db712 | |
dependabot[bot] | d03e43facc | |
dependabot[bot] | c2ed82f3af | |
dependabot[bot] | 5fc71dec34 | |
Rob Bradford | d10f20eb71 | |
Rob Bradford | 6c0dedd560 | |
Rob Bradford | b29edfbee8 | |
Bo Chen | 75e1dc2bce | |
dependabot[bot] | 6ba4f6de95 | |
Purna Pavan Chandra | de1f055481 | |
Purna Pavan Chandra | 1a94c6c932 | |
Wei Liu | 1aeaee221d | |
Wei Liu | 862a056105 | |
Wei Liu | fe704bd44a | |
Wei Liu | f6cd3bd86d | |
Wei Liu | 0816c8292f | |
Wei Liu | 319538fbed | |
Wei Liu | 4f1e74b553 | |
dependabot[bot] | 24f8d15b14 | |
Rob Bradford | f4b0443489 | |
Muminul Islam | 030d84eb08 | |
Muminul Islam | 4847f5c4f6 | |
Muminul Islam | bf6c9e6447 | |
Wei Liu | f6d99d9a9b | |
Songqian Li | e38a69f0d2 | |
Rob Bradford | 4f96fa15a8 | |
dependabot[bot] | ed1f906d46 | |
Thomas Barrett | 3b64b7723b | |
dependabot[bot] | 6925750622 | |
dependabot[bot] | 26808bfb71 | |
Rob Bradford | b89657ea22 | |
Rob Bradford | 1ef2b488c7 | |
Rob Bradford | 7be69edf51 | |
Rob Bradford | c022063ae8 | |
dependabot[bot] | e6aa57e3b9 | |
Muminul Islam | 512591ba1c | |
Thomas Barrett | e7e856d8ac | |
dependabot[bot] | a84bc06874 | |
Muminul Islam | a750e6ec15 | |
dependabot[bot] | 82d275ccaa | |
Rob Bradford | 10ab87d6a3 |
|
@ -15,7 +15,7 @@ jobs:
|
|||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
- "1.74.1"
|
||||
- "1.77.0"
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- x86_64-unknown-linux-musl
|
||||
|
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=20240407-0
|
||||
type=raw,value=20240507-0
|
||||
type=sha
|
||||
|
||||
- name: Build and push
|
||||
|
|
|
@ -88,6 +88,7 @@ jobs:
|
|||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
./${{ matrix.platform.name_ch }}
|
||||
./${{ matrix.platform.name_ch_remote }}
|
||||
|
|
|
@ -115,8 +115,6 @@ dependencies = [
|
|||
"serde",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-fdt",
|
||||
"vm-memory",
|
||||
"vm-migration",
|
||||
|
@ -249,9 +247,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5"
|
||||
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -278,9 +276,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.0"
|
||||
version = "4.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
|
||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
|
@ -320,15 +318,6 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitfield-struct"
|
||||
version = "0.5.6"
|
||||
|
@ -362,11 +351,10 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"remain",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
|
@ -413,9 +401,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.92"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
|
||||
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -453,7 +441,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
|||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "38.0.0"
|
||||
version = "39.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
|
@ -490,9 +478,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
|||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363"
|
||||
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
@ -524,12 +512,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc64"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.19"
|
||||
|
@ -612,10 +594,9 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"pci",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tpm",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-allocator",
|
||||
"vm-device",
|
||||
"vm-memory",
|
||||
|
@ -1090,8 +1071,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||
|
||||
[[package]]
|
||||
name = "igvm"
|
||||
version = "0.1.9"
|
||||
source = "git+https://github.com/microsoft/igvm?branch=main#494aac2318df4111a2737d360ea46f74f5350223"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac310e8c44854718e087821efe5d30ed18f3f864b3926b777ef70aadbb9834d"
|
||||
dependencies = [
|
||||
"bitfield-struct",
|
||||
"crc32fast",
|
||||
|
@ -1106,8 +1088,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "igvm_defs"
|
||||
version = "0.1.9"
|
||||
source = "git+https://github.com/microsoft/igvm?branch=main#494aac2318df4111a2737d360ea46f74f5350223"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a57e85ae9109a6281a1fc279456f830237a94a65873a331ad858814b1a09b2b"
|
||||
dependencies = [
|
||||
"bitfield-struct",
|
||||
"open-enum",
|
||||
|
@ -1181,19 +1164,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "kvm-bindings"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.7.0#2dcf85d4f8aa55befcaa996b699ddb18ec9ed059"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82e7e8725a39a0015e511a46cc1f7d90cecc180db1610c4d0d4339a9e48bd21"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"vmm-sys-util",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kvm-ioctls"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c"
|
||||
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"kvm-bindings",
|
||||
|
@ -1343,7 +1327,7 @@ checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07"
|
|||
[[package]]
|
||||
name = "mshv-bindings"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#ef8fd01cf48b2e72bd6405a613a6ef65b43729d7"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#76bbc508a4152d020dd42061d4505c64e320ba94"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num_enum",
|
||||
|
@ -1356,7 +1340,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "mshv-ioctls"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#ef8fd01cf48b2e72bd6405a613a6ef65b43729d7"
|
||||
source = "git+https://github.com/rust-vmm/mshv?branch=main#76bbc508a4152d020dd42061d4505c64e320ba94"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mshv-bindings",
|
||||
|
@ -1396,8 +1380,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
|
@ -1600,8 +1582,6 @@ dependencies = [
|
|||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-bindings",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
|
@ -2210,18 +2190,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.58"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
|
||||
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.58"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2356,37 +2336,10 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.109",
|
||||
"versionize_derive",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize_derive"
|
||||
version = "0.1.6"
|
||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vfio-bindings"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#4e937a514d9025f953eeb837fb8dafe035d9a8fd"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#df7de6b256a1ece422804119938f6a325b2ce99b"
|
||||
dependencies = [
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
@ -2394,7 +2347,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "vfio-ioctls"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#4e937a514d9025f953eeb837fb8dafe035d9a8fd"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#df7de6b256a1ece422804119938f6a325b2ce99b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"kvm-bindings",
|
||||
|
@ -2428,9 +2381,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vhost"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
|
||||
checksum = "6be08d1166d41a78861ad50212ab3f9eca0729c349ac3a7a8f557c62406b87cc"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
|
@ -2440,9 +2393,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vhost-user-backend"
|
||||
version = "0.13.1"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c8c447d076ac508d78cb45664d203df7989e891656dce260a7e93d72352c9a"
|
||||
checksum = "1f0ffb1dd8e00a708a0e2c32d5efec5812953819888591fff9ff68236b8a5096"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
|
@ -2515,10 +2468,9 @@ dependencies = [
|
|||
"seccompiler",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serial_buffer",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vhost",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
|
@ -2532,9 +2484,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "virtio-queue"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d"
|
||||
checksum = "07d8406e7250c934462de585d8f2d2781c31819bca1fbb7c5e964ca6bbaabfe8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"virtio-bindings",
|
||||
|
@ -2589,8 +2541,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
|
@ -2617,6 +2567,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"clap",
|
||||
"devices",
|
||||
"dhat",
|
||||
"epoll",
|
||||
"event_monitor",
|
||||
"flume",
|
||||
|
@ -2646,8 +2597,6 @@ dependencies = [
|
|||
"thiserror",
|
||||
"tracer",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
"virtio-devices",
|
||||
|
|
13
Cargo.toml
13
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "cloud-hypervisor"
|
||||
version = "38.0.0"
|
||||
version = "39.0.0"
|
||||
authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
default-run = "cloud-hypervisor"
|
||||
|
@ -15,7 +15,7 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
|||
# a.) A dependency requires it,
|
||||
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
|
||||
# c.) There is a security issue that is addressed by the toolchain update.
|
||||
rust-version = "1.74.1"
|
||||
rust-version = "1.77.0"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
@ -42,7 +42,7 @@ option_parser = { path = "option_parser" }
|
|||
seccompiler = "0.4.0"
|
||||
serde_json = "1.0.115"
|
||||
signal-hook = "0.3.17"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
tpm = { path = "tpm"}
|
||||
tracer = { path = "tracer" }
|
||||
vmm = { path = "vmm" }
|
||||
|
@ -50,11 +50,6 @@ vmm-sys-util = "0.12.1"
|
|||
vm-memory = "0.14.1"
|
||||
zbus = { version = "3.15.2", optional = true }
|
||||
|
||||
# List of patched crates
|
||||
[patch.crates-io]
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0" }
|
||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
|
||||
|
||||
[dev-dependencies]
|
||||
dirs = "5.0.1"
|
||||
net_util = { path = "net_util" }
|
||||
|
@ -68,7 +63,7 @@ wait-timeout = "0.2.0"
|
|||
[features]
|
||||
default = ["kvm", "io_uring"]
|
||||
dbus_api = ["zbus", "vmm/dbus_api"]
|
||||
dhat-heap = ["dhat"] # For heap profiling
|
||||
dhat-heap = ["dhat", "vmm/dhat-heap"] # For heap profiling
|
||||
guest_debug = ["vmm/guest_debug"]
|
||||
igvm = ["vmm/igvm", "mshv"]
|
||||
io_uring = ["vmm/io_uring"]
|
||||
|
|
|
@ -17,10 +17,8 @@ libc = "0.2.153"
|
|||
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
uuid = "1.8.0"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-bitmap"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
|
||||
|
|
|
@ -18,9 +18,6 @@ use std::fmt;
|
|||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_migration::VersionMapped;
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||
|
@ -58,7 +55,7 @@ pub enum Error {
|
|||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// Type for memory region types.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum RegionType {
|
||||
/// RAM type
|
||||
Ram,
|
||||
|
@ -76,8 +73,6 @@ pub enum RegionType {
|
|||
Reserved,
|
||||
}
|
||||
|
||||
impl VersionMapped for RegionType {}
|
||||
|
||||
/// Module for aarch64 related functionality.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub mod aarch64;
|
||||
|
|
|
@ -17,7 +17,7 @@ pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct mpf_intel {
|
||||
pub signature: [::std::os::raw::c_char; 4usize],
|
||||
pub signature: [::std::os::raw::c_uchar; 4usize],
|
||||
pub physptr: ::std::os::raw::c_uint,
|
||||
pub length: ::std::os::raw::c_uchar,
|
||||
pub specification: ::std::os::raw::c_uchar,
|
||||
|
@ -32,12 +32,12 @@ pub struct mpf_intel {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct mpc_table {
|
||||
pub signature: [::std::os::raw::c_char; 4usize],
|
||||
pub signature: [::std::os::raw::c_uchar; 4usize],
|
||||
pub length: ::std::os::raw::c_ushort,
|
||||
pub spec: ::std::os::raw::c_char,
|
||||
pub checksum: ::std::os::raw::c_char,
|
||||
pub oem: [::std::os::raw::c_char; 8usize],
|
||||
pub productid: [::std::os::raw::c_char; 12usize],
|
||||
pub spec: ::std::os::raw::c_uchar,
|
||||
pub checksum: ::std::os::raw::c_uchar,
|
||||
pub oem: [::std::os::raw::c_uchar; 8usize],
|
||||
pub productid: [::std::os::raw::c_uchar; 12usize],
|
||||
pub oemptr: ::std::os::raw::c_uint,
|
||||
pub oemsize: ::std::os::raw::c_ushort,
|
||||
pub oemcount: ::std::os::raw::c_ushort,
|
||||
|
@ -106,9 +106,9 @@ pub struct mpc_lintsrc {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct mpc_oemtable {
|
||||
pub signature: [::std::os::raw::c_char; 4usize],
|
||||
pub signature: [::std::os::raw::c_uchar; 4usize],
|
||||
pub length: ::std::os::raw::c_ushort,
|
||||
pub rev: ::std::os::raw::c_char,
|
||||
pub checksum: ::std::os::raw::c_char,
|
||||
pub mpc: [::std::os::raw::c_char; 8usize],
|
||||
pub rev: ::std::os::raw::c_uchar,
|
||||
pub checksum: ::std::os::raw::c_uchar,
|
||||
pub mpc: [::std::os::raw::c_uchar; 8usize],
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
|
||||
use crate::x86_64::{get_x2apic_id, mpspec};
|
||||
use crate::GuestMemoryMmap;
|
||||
use libc::c_char;
|
||||
use libc::c_uchar;
|
||||
use std::mem;
|
||||
use std::result;
|
||||
use std::slice;
|
||||
|
@ -82,18 +82,13 @@ pub type Result<T> = result::Result<T, Error>;
|
|||
// a large number for FC usecases.
|
||||
pub const MAX_SUPPORTED_CPUS: u32 = 254;
|
||||
|
||||
// Convenience macro for making arrays of diverse character types.
|
||||
macro_rules! char_array {
|
||||
($t:ty; $( $c:expr ),*) => ( [ $( $c as $t ),* ] )
|
||||
}
|
||||
|
||||
// Most of these variables are sourced from the Intel MP Spec 1.4.
|
||||
const SMP_MAGIC_IDENT: [c_char; 4] = char_array!(c_char; '_', 'M', 'P', '_');
|
||||
const MPC_SIGNATURE: [c_char; 4] = char_array!(c_char; 'P', 'C', 'M', 'P');
|
||||
const MPC_SPEC: i8 = 4;
|
||||
const MPC_OEM: [c_char; 8] = char_array!(c_char; 'F', 'C', ' ', ' ', ' ', ' ', ' ', ' ');
|
||||
const MPC_PRODUCT_ID: [c_char; 12] = ['0' as c_char; 12];
|
||||
const BUS_TYPE_ISA: [u8; 6] = char_array!(u8; 'I', 'S', 'A', ' ', ' ', ' ');
|
||||
const SMP_MAGIC_IDENT: &[c_uchar; 4] = b"_MP_";
|
||||
const MPC_SIGNATURE: &[c_uchar; 4] = b"PCMP";
|
||||
const MPC_SPEC: u8 = 4;
|
||||
const MPC_OEM: &[c_uchar; 8] = b"FC ";
|
||||
const MPC_PRODUCT_ID: &[c_uchar; 12] = &[b'0'; 12];
|
||||
const BUS_TYPE_ISA: &[c_uchar; 6] = b"ISA ";
|
||||
const APIC_VERSION: u8 = 0x14;
|
||||
const CPU_STEPPING: u32 = 0x600;
|
||||
const CPU_FEATURE_APIC: u32 = 0x200;
|
||||
|
@ -168,7 +163,7 @@ pub fn setup_mptable(
|
|||
{
|
||||
let mut mpf_intel = MpfIntelWrapper(mpspec::mpf_intel::default());
|
||||
let size = mem::size_of::<MpfIntelWrapper>() as u64;
|
||||
mpf_intel.0.signature = SMP_MAGIC_IDENT;
|
||||
mpf_intel.0.signature = *SMP_MAGIC_IDENT;
|
||||
mpf_intel.0.length = 1;
|
||||
mpf_intel.0.specification = 4;
|
||||
mpf_intel.0.physptr = (base_mp.raw_value() + size) as u32;
|
||||
|
@ -209,7 +204,7 @@ pub fn setup_mptable(
|
|||
let mut mpc_bus = MpcBusWrapper(mpspec::mpc_bus::default());
|
||||
mpc_bus.0.type_ = mpspec::MP_BUS as u8;
|
||||
mpc_bus.0.busid = 0;
|
||||
mpc_bus.0.bustype = BUS_TYPE_ISA;
|
||||
mpc_bus.0.bustype = *BUS_TYPE_ISA;
|
||||
mem.write_obj(mpc_bus, base_mp)
|
||||
.map_err(Error::WriteMpcBus)?;
|
||||
base_mp = base_mp.unchecked_add(size as u64);
|
||||
|
@ -280,14 +275,14 @@ pub fn setup_mptable(
|
|||
|
||||
{
|
||||
let mut mpc_table = MpcTableWrapper(mpspec::mpc_table::default());
|
||||
mpc_table.0.signature = MPC_SIGNATURE;
|
||||
mpc_table.0.signature = *MPC_SIGNATURE;
|
||||
mpc_table.0.length = table_end.unchecked_offset_from(table_base) as u16;
|
||||
mpc_table.0.spec = MPC_SPEC;
|
||||
mpc_table.0.oem = MPC_OEM;
|
||||
mpc_table.0.productid = MPC_PRODUCT_ID;
|
||||
mpc_table.0.oem = *MPC_OEM;
|
||||
mpc_table.0.productid = *MPC_PRODUCT_ID;
|
||||
mpc_table.0.lapic = APIC_START.0 as u32;
|
||||
checksum = checksum.wrapping_add(compute_checksum(&mpc_table.0));
|
||||
mpc_table.0.checksum = (!checksum).wrapping_add(1) as i8;
|
||||
mpc_table.0.checksum = (!checksum).wrapping_add(1);
|
||||
mem.write_obj(mpc_table, table_base)
|
||||
.map_err(Error::WriteMpcTable)?;
|
||||
}
|
||||
|
|
|
@ -15,13 +15,12 @@ io-uring = { version = "0.6.3", optional = true }
|
|||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
remain = "0.2.13"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
smallvec = "1.13.2"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
uuid = { version = "1.8.0", features = ["v4"] }
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
|
|
@ -37,6 +37,7 @@ use crate::vhdx::{Vhdx, VhdxError};
|
|||
#[cfg(feature = "io_uring")]
|
||||
use io_uring::{opcode, IoUring, Probe};
|
||||
use libc::{ioctl, S_IFBLK, S_IFMT};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||
use std::cmp;
|
||||
|
@ -52,21 +53,17 @@ use std::sync::Arc;
|
|||
use std::sync::MutexGuard;
|
||||
use std::time::Instant;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_bindings::virtio_blk::*;
|
||||
use virtio_queue::DescriptorChain;
|
||||
use vm_memory::{
|
||||
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
|
||||
GuestMemoryError, GuestMemoryLoadGuard,
|
||||
bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError,
|
||||
GuestMemoryLoadGuard,
|
||||
};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::aio;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||
|
||||
const SECTOR_SHIFT: u8 = 9;
|
||||
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
|
||||
|
||||
|
@ -196,8 +193,8 @@ pub enum RequestType {
|
|||
Unsupported(u32),
|
||||
}
|
||||
|
||||
pub fn request_type(
|
||||
mem: &GuestMemoryMmap,
|
||||
pub fn request_type<B: Bitmap + 'static>(
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
desc_addr: GuestAddress,
|
||||
) -> result::Result<RequestType, Error> {
|
||||
let type_ = mem.read_obj(desc_addr).map_err(Error::GuestMemory)?;
|
||||
|
@ -210,7 +207,10 @@ pub fn request_type(
|
|||
}
|
||||
}
|
||||
|
||||
fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64, Error> {
|
||||
fn sector<B: Bitmap + 'static>(
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
desc_addr: GuestAddress,
|
||||
) -> result::Result<u64, Error> {
|
||||
const SECTOR_OFFSET: usize = 8;
|
||||
let addr = match mem.checked_offset(desc_addr, SECTOR_OFFSET) {
|
||||
Some(v) => v,
|
||||
|
@ -240,8 +240,8 @@ pub struct Request {
|
|||
}
|
||||
|
||||
impl Request {
|
||||
pub fn parse(
|
||||
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap>>,
|
||||
pub fn parse<B: Bitmap + 'static>(
|
||||
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
|
||||
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
||||
) -> result::Result<Request, Error> {
|
||||
let hdr_desc = desc_chain
|
||||
|
@ -332,11 +332,11 @@ impl Request {
|
|||
Ok(req)
|
||||
}
|
||||
|
||||
pub fn execute<T: Seek + Read + Write>(
|
||||
pub fn execute<T: Seek + Read + Write, B: Bitmap + 'static>(
|
||||
&self,
|
||||
disk: &mut T,
|
||||
disk_nsectors: u64,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
serial: &[u8],
|
||||
) -> result::Result<u32, ExecuteError> {
|
||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||
|
@ -389,9 +389,9 @@ impl Request {
|
|||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn execute_async(
|
||||
pub fn execute_async<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
disk_nsectors: u64,
|
||||
disk_image: &mut dyn AsyncIo,
|
||||
serial: &[u8],
|
||||
|
@ -544,7 +544,7 @@ impl Request {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioBlockConfig {
|
||||
pub capacity: u64,
|
||||
|
@ -567,7 +567,7 @@ pub struct VirtioBlockConfig {
|
|||
pub write_zeroes_may_unmap: u8,
|
||||
pub unused1: [u8; 3],
|
||||
}
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioBlockGeometry {
|
||||
pub cylinders: u16,
|
||||
|
@ -659,7 +659,9 @@ where
|
|||
let mut slices: SmallVec<[IoSliceMut; 1]> = SmallVec::with_capacity(iovecs.len());
|
||||
for iovec in iovecs.iter() {
|
||||
// SAFETY: on Linux IoSliceMut wraps around libc::iovec
|
||||
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
slices.push(IoSliceMut::new(unsafe {
|
||||
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
|
||||
}));
|
||||
}
|
||||
|
||||
let result = {
|
||||
|
@ -692,7 +694,9 @@ where
|
|||
let mut slices: SmallVec<[IoSlice; 1]> = SmallVec::with_capacity(iovecs.len());
|
||||
for iovec in iovecs.iter() {
|
||||
// SAFETY: on Linux IoSlice wraps around libc::iovec
|
||||
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
slices.push(IoSlice::new(unsafe {
|
||||
std::mem::transmute::<libc::iovec, &mut [u8]>(*iovec)
|
||||
}));
|
||||
}
|
||||
|
||||
let result = {
|
||||
|
|
|
@ -1631,7 +1631,7 @@ impl PunchHole for QcowFile {
|
|||
let mut remaining = length;
|
||||
let mut offset = offset;
|
||||
while remaining > 0 {
|
||||
let chunk_length = min(remaining, std::usize::MAX as u64) as usize;
|
||||
let chunk_length = min(remaining, usize::MAX as u64) as usize;
|
||||
self.deallocate_bytes(offset, chunk_length)?;
|
||||
remaining -= chunk_length as u64;
|
||||
offset += chunk_length as u64;
|
||||
|
|
|
@ -15,10 +15,9 @@ hypervisor = { path = "../hypervisor" }
|
|||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
pci = { path = "../pci" }
|
||||
thiserror = "1.0.58"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
thiserror = "1.0.60"
|
||||
tpm = { path = "../tpm" }
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = "0.14.1"
|
||||
|
|
|
@ -11,19 +11,16 @@
|
|||
|
||||
use super::interrupt_controller::{Error, InterruptController};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
||||
MsiIrqGroupConfig, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_device::BusDevice;
|
||||
use vm_memory::GuestAddress;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
|
@ -136,7 +133,7 @@ pub struct Ioapic {
|
|||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct IoapicState {
|
||||
id_reg: u32,
|
||||
reg_sel: u32,
|
||||
|
@ -144,7 +141,6 @@ pub struct IoapicState {
|
|||
used_entries: [bool; NUM_IOAPIC_PINS],
|
||||
apic_address: u64,
|
||||
}
|
||||
impl VersionMapped for IoapicState {}
|
||||
|
||||
impl BusDevice for Ioapic {
|
||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||
|
@ -444,7 +440,7 @@ impl Snapshottable for Ioapic {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,16 +8,13 @@
|
|||
//!
|
||||
|
||||
use crate::{read_le_u32, write_le_u32};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{fmt, io};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
|
||||
const OFS_DATA: u64 = 0x400; // Data Register
|
||||
const GPIODIR: u64 = 0x400; // Direction Register
|
||||
|
@ -89,7 +86,7 @@ pub struct Gpio {
|
|||
interrupt: Arc<dyn InterruptSourceGroup>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GpioState {
|
||||
data: u32,
|
||||
old_in_data: u32,
|
||||
|
@ -102,8 +99,6 @@ pub struct GpioState {
|
|||
afsel: u32,
|
||||
}
|
||||
|
||||
impl VersionMapped for GpioState {}
|
||||
|
||||
impl Gpio {
|
||||
/// Constructs an PL061 GPIO device.
|
||||
pub fn new(
|
||||
|
@ -328,7 +323,7 @@ impl Snapshottable for Gpio {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -153,24 +153,6 @@ impl fmt::Display for LocalTime {
|
|||
}
|
||||
}
|
||||
|
||||
/// Holds a micro-second resolution timestamp with both the real time and cpu time.
|
||||
#[derive(Clone)]
|
||||
pub struct TimestampUs {
|
||||
/// Real time in microseconds.
|
||||
pub time_us: u64,
|
||||
/// Cpu time in microseconds.
|
||||
pub cputime_us: u64,
|
||||
}
|
||||
|
||||
impl Default for TimestampUs {
|
||||
fn default() -> TimestampUs {
|
||||
TimestampUs {
|
||||
time_us: get_time(ClockType::Monotonic) / 1000,
|
||||
cputime_us: get_time(ClockType::ProcessCpu) / 1000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a timestamp in nanoseconds based on the provided clock type.
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
|
@ -5,16 +5,13 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{io, result};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::errno::Result;
|
||||
|
||||
const LOOP_SIZE: usize = 0x40;
|
||||
|
@ -74,7 +71,7 @@ pub struct Serial {
|
|||
out: Option<Box<dyn io::Write + Send>>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SerialState {
|
||||
interrupt_enable: u8,
|
||||
interrupt_identification: u8,
|
||||
|
@ -86,7 +83,6 @@ pub struct SerialState {
|
|||
baud_divisor: u16,
|
||||
in_buffer: Vec<u8>,
|
||||
}
|
||||
impl VersionMapped for SerialState {}
|
||||
|
||||
impl Serial {
|
||||
pub fn new(
|
||||
|
@ -334,7 +330,7 @@ impl Snapshottable for Serial {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,15 @@
|
|||
//!
|
||||
|
||||
use crate::{read_le_u32, write_le_u32};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::Instant;
|
||||
use std::{io, result};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
|
||||
/* Registers */
|
||||
const UARTDR: u64 = 0;
|
||||
|
@ -94,7 +91,7 @@ pub struct Pl011 {
|
|||
timestamp: std::time::Instant,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Pl011State {
|
||||
flags: u32,
|
||||
lcr: u32,
|
||||
|
@ -113,8 +110,6 @@ pub struct Pl011State {
|
|||
read_trigger: u32,
|
||||
}
|
||||
|
||||
impl VersionMapped for Pl011State {}
|
||||
|
||||
impl Pl011 {
|
||||
/// Constructs an AMBA PL011 UART device.
|
||||
pub fn new(
|
||||
|
@ -454,7 +449,7 @@ impl Snapshottable for Pl011 {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,15 @@ use pci::{
|
|||
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
||||
PCI_CONFIGURATION_ID,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::{BusDevice, Resource};
|
||||
use vm_memory::{Address, GuestAddress};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
|
||||
const PVPANIC_VENDOR_ID: u16 = 0x1b36;
|
||||
const PVPANIC_DEVICE_ID: u16 = 0x0011;
|
||||
|
@ -60,23 +57,20 @@ pub struct PvPanicDevice {
|
|||
bar_regions: Vec<PciBarConfiguration>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PvPanicDeviceState {
|
||||
events: u8,
|
||||
}
|
||||
|
||||
impl VersionMapped for PvPanicDeviceState {}
|
||||
|
||||
impl PvPanicDevice {
|
||||
pub fn new(id: String, snapshot: Option<Snapshot>) -> Result<Self, PvPanicError> {
|
||||
let pci_configuration_state =
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
|
||||
.map_err(|e| {
|
||||
PvPanicError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
|
||||
PvPanicError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let mut configuration = PciConfiguration::new(
|
||||
PVPANIC_VENDOR_ID,
|
||||
|
@ -97,7 +91,7 @@ impl PvPanicDevice {
|
|||
|
||||
let state: Option<PvPanicDeviceState> = snapshot
|
||||
.as_ref()
|
||||
.map(|s| s.to_versioned_state())
|
||||
.map(|s| s.to_state())
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
PvPanicError::CreatePvPanicDevice(anyhow!(
|
||||
|
@ -259,7 +253,7 @@ impl Snapshottable for PvPanicDevice {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
let mut snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||
let mut snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
|
||||
|
|
62
docs/vfio.md
62
docs/vfio.md
|
@ -122,4 +122,64 @@ $ ls /sys/kernel/iommu_groups/22/devices/
|
|||
|
||||
This means these two devices are under the same IOMMU group 22. In such case,
|
||||
it is important to bind both devices to VFIO and pass them both through the
|
||||
VM, otherwise this could cause some functional and security issues.
|
||||
VM, otherwise this could cause some functional and security issues.
|
||||
|
||||
### Advanced Configuration Options
|
||||
|
||||
When using NVIDIA GPUs in a VFIO passthrough configuration, advanced
|
||||
configuration options are supported to enable GPUDirect P2P DMA over
|
||||
PCIe. When enabled, loads and stores between GPUs use native PCIe
|
||||
peer-to-peer transactions instead of a shared memory buffer. This drastically
|
||||
decreases P2P latency between GPUs. This functionality is supported by
|
||||
cloud-hypervisor on NVIDIA Turing, Ampere, Hopper, and Lovelace GPUs.
|
||||
|
||||
The NVIDIA driver does not enable GPUDirect P2P over PCIe within guests
|
||||
by default because hardware support for routing P2P TLP between PCIe root
|
||||
ports is optional. PCIe P2P should always be supported between devices
|
||||
on the same PCIe switch. The `x_nv_gpudirect_clique` config argument may
|
||||
be used to signal support for PCIe P2P traffic between NVIDIA VFIO endpoints.
|
||||
The guest driver assumes that P2P traffic is supported between all endpoints
|
||||
that are part of the same clique.
|
||||
```
|
||||
--device path=/sys/bus/pci/devices/0000:01:00.0/,x_nv_gpudirect_clique=0
|
||||
```
|
||||
|
||||
The following command can be run on the guest to verify that GPUDirect P2P is
|
||||
correctly enabled.
|
||||
```
|
||||
nvidia-smi topo -p2p r
|
||||
GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7
|
||||
GPU0 X OK OK OK OK OK OK OK
|
||||
GPU1 OK X OK OK OK OK OK OK
|
||||
GPU2 OK OK X OK OK OK OK OK
|
||||
GPU3 OK OK OK X OK OK OK OK
|
||||
GPU4 OK OK OK OK X OK OK OK
|
||||
GPU5 OK OK OK OK OK X OK OK
|
||||
GPU6 OK OK OK OK OK OK X OK
|
||||
GPU7 OK OK OK OK OK OK OK X
|
||||
```
|
||||
|
||||
Some VFIO devices have a 32-bit mmio BAR. When using many such devices, it is
|
||||
possible to exhaust the 32-bit mmio space available on a PCI segment. The
|
||||
following example demonstrates an example device with a 16 MiB 32-bit mmio BAR.
|
||||
```
|
||||
lspci -s 0000:01:00.0 -v
|
||||
0000:01:00.0 3D controller: NVIDIA Corporation Device 26b9 (rev a1)
|
||||
[...]
|
||||
Memory at f9000000 (32-bit, non-prefetchable) [size=16M]
|
||||
Memory at 46000000000 (64-bit, prefetchable) [size=64G]
|
||||
Memory at 48040000000 (64-bit, prefetchable) [size=32M]
|
||||
[...]
|
||||
```
|
||||
|
||||
When using multiple PCI segments, the 32-bit mmio address space available to
|
||||
be allocated to VFIO devices is equally split between all PCI segments by
|
||||
default. This can be tuned with the `--pci-segment` flag. The following example
|
||||
demonstrates a guest with two PCI segments. 2/3 of the 32-bit mmio address
|
||||
space is available for use by devices on PCI segment 0 and 1/3 of the 32-bit
|
||||
mmio address space is available for use by devices on PCI segment 1.
|
||||
```
|
||||
--platform num_pci_segments=2
|
||||
--pci-segment pci_segment=0,mmio32_aperture_weight=2
|
||||
--pci-segment pci_segment=1,mmio32_aperture_weight=1
|
||||
```
|
||||
|
|
|
@ -50,9 +50,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.2"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
|
@ -97,8 +97,6 @@ dependencies = [
|
|||
"serde",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-fdt",
|
||||
"vm-memory",
|
||||
"vm-migration",
|
||||
|
@ -107,18 +105,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
|
@ -142,11 +131,10 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"remain",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
|
@ -211,7 +199,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
|||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "38.0.0"
|
||||
version = "39.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
|
@ -273,12 +261,6 @@ dependencies = [
|
|||
"debug-helper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc64"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.8"
|
||||
|
@ -300,7 +282,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.10.0",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -311,7 +293,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
|||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -334,10 +316,9 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"pci",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tpm",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-allocator",
|
||||
"vm-device",
|
||||
"vm-memory",
|
||||
|
@ -457,9 +438,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.30"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
|
||||
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -475,19 +456,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "kvm-bindings"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.7.0#2dcf85d4f8aa55befcaa996b699ddb18ec9ed059"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82e7e8725a39a0015e511a46cc1f7d90cecc180db1610c4d0d4339a9e48bd21"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"vmm-sys-util",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kvm-ioctls"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c"
|
||||
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"kvm-bindings",
|
||||
|
@ -497,9 +479,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
|
@ -574,8 +556,6 @@ dependencies = [
|
|||
"rate_limiter",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
|
@ -604,8 +584,6 @@ dependencies = [
|
|||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-bindings",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
|
@ -618,9 +596,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.79"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -653,7 +631,7 @@ checksum = "ad9f2390298a947ee0aa6073d440e221c0726188cfbcdf9604addb6ee393eb4a"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -679,22 +657,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
version = "1.0.198"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
version = "1.0.198"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -710,9 +688,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.7.0"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
|
||||
checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -721,14 +699,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.7.0"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
|
||||
checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -747,9 +725,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -783,20 +761,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
version = "2.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -820,7 +787,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -868,37 +835,10 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.109",
|
||||
"versionize_derive",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize_derive"
|
||||
version = "0.1.6"
|
||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vfio-bindings"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
|
||||
dependencies = [
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
@ -906,7 +846,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "vfio-ioctls"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"kvm-bindings",
|
||||
|
@ -938,9 +878,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "vhost"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
|
||||
checksum = "6be08d1166d41a78861ad50212ab3f9eca0729c349ac3a7a8f557c62406b87cc"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
|
@ -973,10 +913,9 @@ dependencies = [
|
|||
"seccompiler",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serial_buffer",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vhost",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
|
@ -990,9 +929,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "virtio-queue"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d"
|
||||
checksum = "07d8406e7250c934462de585d8f2d2781c31819bca1fbb7c5e964ca6bbaabfe8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"virtio-bindings",
|
||||
|
@ -1047,8 +986,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
|
@ -1095,8 +1032,6 @@ dependencies = [
|
|||
"thiserror",
|
||||
"tracer",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
"virtio-devices",
|
||||
|
@ -1149,7 +1084,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -1171,7 +1106,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -1215,13 +1150,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
|
@ -1230,15 +1166,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -1246,6 +1182,12 @@ version = "0.52.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
|
@ -1260,9 +1202,9 @@ checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -1288,5 +1230,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.58",
|
||||
"syn",
|
||||
]
|
||||
|
|
|
@ -15,7 +15,7 @@ igvm = []
|
|||
block = { path = "../block" }
|
||||
devices = { path = "../devices" }
|
||||
epoll = "4.3.3"
|
||||
libc = "0.2.153"
|
||||
libc = "0.2.154"
|
||||
libfuzzer-sys = "0.4.7"
|
||||
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
|
||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
||||
|
@ -23,8 +23,8 @@ net_util = { path = "../net_util" }
|
|||
once_cell = "1.19.0"
|
||||
seccompiler = "0.4.0"
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
virtio-queue = "0.11.0"
|
||||
vmm = { path = "../vmm" }
|
||||
virtio-queue = "0.12.0"
|
||||
vmm = { path = "../vmm", features = ["guest_debug"]}
|
||||
vmm-sys-util = "0.12.1"
|
||||
vm-memory = "0.14.1"
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
|
@ -34,10 +34,6 @@ vm-virtio = { path = "../vm-virtio" }
|
|||
[dependencies.cloud-hypervisor]
|
||||
path = ".."
|
||||
|
||||
[patch.crates-io]
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0" }
|
||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
|
|
@ -105,7 +105,7 @@ impl RequestHandler for StubApiRequestHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn vm_coredump(&mut self, _: &str) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ impl RequestHandler for StubApiRequestHandler {
|
|||
sgx_epc: None,
|
||||
numa: None,
|
||||
watchdog: false,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb: false,
|
||||
pci_segments: None,
|
||||
platform: None,
|
||||
tpm: None,
|
||||
preserved_fds: None,
|
||||
|
|
|
@ -8,18 +8,18 @@ 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", "iced-x86"]
|
||||
sev_snp = ["igvm_parser", "igvm_defs"]
|
||||
sev_snp = ["igvm", "igvm_defs"]
|
||||
tdx = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
byteorder = "1.5.0"
|
||||
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
|
||||
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
|
||||
igvm = { version = "0.2.0", optional = true }
|
||||
igvm_defs = { version = "0.2.0", optional = true }
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
kvm-ioctls = { version = "0.16.0", optional = true }
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.7.0", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||
kvm-bindings = { version = "0.8.1", optional = true, features = ["serde"] }
|
||||
kvm-ioctls = { version = "0.17.0", 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.197", features = ["rc", "derive"] }
|
||||
|
@ -27,7 +27,7 @@ serde_with = { version = "3.7.0", default-features = false, features = ["macros"
|
|||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }
|
||||
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||
optional = true
|
||||
|
|
|
@ -53,7 +53,6 @@ pub enum Exception {
|
|||
pub mod regs;
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct SegmentRegister {
|
||||
pub base: u64,
|
||||
pub limit: u32,
|
||||
|
@ -174,7 +173,6 @@ macro_rules! msr_data {
|
|||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct StandardRegisters {
|
||||
pub rax: u64,
|
||||
pub rbx: u64,
|
||||
|
@ -197,14 +195,12 @@ pub struct StandardRegisters {
|
|||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct DescriptorTable {
|
||||
pub base: u64,
|
||||
pub limit: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
|
||||
pub struct SpecialRegisters {
|
||||
pub cs: SegmentRegister,
|
||||
pub ds: SegmentRegister,
|
||||
|
|
|
@ -107,14 +107,28 @@ pub enum HypervisorCpuError {
|
|||
///
|
||||
/// Setting Saved Processor Extended States error
|
||||
///
|
||||
#[cfg(feature = "kvm")]
|
||||
#[error("Failed to set Saved Processor Extended States: {0}")]
|
||||
SetXsaveState(#[source] anyhow::Error),
|
||||
///
|
||||
/// Getting Saved Processor Extended States error
|
||||
///
|
||||
#[cfg(feature = "kvm")]
|
||||
#[error("Failed to get Saved Processor Extended States: {0}")]
|
||||
GetXsaveState(#[source] anyhow::Error),
|
||||
///
|
||||
/// Getting the VP state components error
|
||||
///
|
||||
#[cfg(feature = "mshv")]
|
||||
#[error("Failed to get VP State Components: {0}")]
|
||||
GetAllVpStateComponents(#[source] anyhow::Error),
|
||||
///
|
||||
/// Setting the VP state components error
|
||||
///
|
||||
#[cfg(feature = "mshv")]
|
||||
#[error("Failed to set VP State Components: {0}")]
|
||||
SetAllVpStateComponents(#[source] anyhow::Error),
|
||||
///
|
||||
/// Setting Extended Control Registers error
|
||||
///
|
||||
#[error("Failed to set Extended Control Registers: {0}")]
|
||||
|
@ -286,15 +300,9 @@ pub enum HypervisorCpuError {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VmExit<'a> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoOut(u16 /* port */, &'a [u8] /* data */),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoIn(u16 /* port */, &'a mut [u8] /* data */),
|
||||
pub enum VmExit {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoapicEoi(u8 /* vector */),
|
||||
MmioRead(u64 /* address */, &'a mut [u8]),
|
||||
MmioWrite(u64 /* address */, &'a [u8]),
|
||||
Ignore,
|
||||
Reset,
|
||||
Shutdown,
|
||||
|
|
|
@ -36,7 +36,6 @@ use std::os::unix::io::RawFd;
|
|||
use std::result;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -455,12 +454,12 @@ impl vm::Vm for KvmVm {
|
|||
id: u8,
|
||||
vm_ops: Option<Arc<dyn VmOps>>,
|
||||
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
||||
let vc = self
|
||||
let fd = self
|
||||
.fd
|
||||
.create_vcpu(id as u64)
|
||||
.map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?;
|
||||
let vcpu = KvmVcpu {
|
||||
fd: vc,
|
||||
fd: Arc::new(Mutex::new(fd)),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: self.msrs.clone(),
|
||||
vm_ops,
|
||||
|
@ -1170,7 +1169,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
|||
|
||||
/// Vcpu struct for KVM
|
||||
pub struct KvmVcpu {
|
||||
fd: VcpuFd,
|
||||
fd: Arc<Mutex<VcpuFd>>,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: Vec<MsrEntry>,
|
||||
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||
|
@ -1198,6 +1197,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_regs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
|
||||
.into())
|
||||
|
@ -1219,6 +1220,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
for i in 0..31 {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.regs[i] = u64::from_le_bytes(bytes);
|
||||
|
@ -1230,6 +1233,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(user_pt_regs, sp);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.sp = u64::from_le_bytes(bytes);
|
||||
|
@ -1238,6 +1243,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(user_pt_regs, pc);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.pc = u64::from_le_bytes(bytes);
|
||||
|
@ -1246,6 +1253,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(user_pt_regs, pstate);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.pstate = u64::from_le_bytes(bytes);
|
||||
|
@ -1254,6 +1263,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(kvm_regs, sp_el1);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.sp_el1 = u64::from_le_bytes(bytes);
|
||||
|
@ -1263,6 +1274,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(kvm_regs, elr_el1);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.elr_el1 = u64::from_le_bytes(bytes);
|
||||
|
@ -1272,6 +1285,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
for i in 0..KVM_NR_SPSR as usize {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.spsr[i] = u64::from_le_bytes(bytes);
|
||||
|
@ -1284,6 +1299,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
for i in 0..32 {
|
||||
let mut bytes = [0_u8; 16];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.vregs[i] = u128::from_le_bytes(bytes);
|
||||
|
@ -1294,6 +1311,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
|
||||
let mut bytes = [0_u8; 4];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.fpsr = u32::from_le_bytes(bytes);
|
||||
|
@ -1302,6 +1321,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
|
||||
let mut bytes = [0_u8; 4];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.fpcr = u32::from_le_bytes(bytes);
|
||||
|
@ -1315,6 +1336,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
|
||||
let regs = (*regs).into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_regs(®s)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into()))
|
||||
}
|
||||
|
@ -1331,6 +1354,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let mut off = offset_of!(user_pt_regs, regs);
|
||||
for i in 0..31 {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.regs[i].to_le_bytes(),
|
||||
|
@ -1341,6 +1366,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(user_pt_regs, sp);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.sp.to_le_bytes(),
|
||||
|
@ -1349,6 +1376,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(user_pt_regs, pc);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.pc.to_le_bytes(),
|
||||
|
@ -1357,6 +1386,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(user_pt_regs, pstate);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.pstate.to_le_bytes(),
|
||||
|
@ -1365,6 +1396,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(kvm_regs, sp_el1);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.sp_el1.to_le_bytes(),
|
||||
|
@ -1373,6 +1406,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(kvm_regs, elr_el1);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.elr_el1.to_le_bytes(),
|
||||
|
@ -1382,6 +1417,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let mut off = offset_of!(kvm_regs, spsr);
|
||||
for i in 0..KVM_NR_SPSR as usize {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.spsr[i].to_le_bytes(),
|
||||
|
@ -1393,6 +1430,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
|
||||
for i in 0..32 {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U128, off),
|
||||
&state.fp_regs.vregs[i].to_le_bytes(),
|
||||
|
@ -1403,6 +1442,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
|
||||
&state.fp_regs.fpsr.to_le_bytes(),
|
||||
|
@ -1411,6 +1452,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
|
||||
&state.fp_regs.fpcr.to_le_bytes(),
|
||||
|
@ -1426,6 +1469,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_sregs(&self) -> cpu::Result<SpecialRegisters> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_sregs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
|
||||
.into())
|
||||
|
@ -1438,6 +1483,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> {
|
||||
let sregs = (*sregs).into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_sregs(&sregs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
|
||||
}
|
||||
|
@ -1449,6 +1496,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_fpu(&self) -> cpu::Result<FpuState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_fpu()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
|
||||
.into())
|
||||
|
@ -1461,6 +1510,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> {
|
||||
let fpu: kvm_bindings::kvm_fpu = (*fpu).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_fpu(&fpu)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into()))
|
||||
}
|
||||
|
@ -1476,6 +1527,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
|
||||
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_cpuid2(&kvm_cpuid)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
|
||||
}
|
||||
|
@ -1494,6 +1547,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
..Default::default()
|
||||
};
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.enable_cap(&cap)
|
||||
.map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into()))
|
||||
}
|
||||
|
@ -1505,6 +1560,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_cpuid2(&self, num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> {
|
||||
let kvm_cpuid = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_cpuid2(num_entries)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCpuid(e.into()))?;
|
||||
|
||||
|
@ -1520,6 +1577,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_lapic(&self) -> cpu::Result<LapicState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_lapic()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
|
||||
.into())
|
||||
|
@ -1532,6 +1591,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn set_lapic(&self, klapic: &LapicState) -> cpu::Result<()> {
|
||||
let klapic: kvm_bindings::kvm_lapic_state = (*klapic).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_lapic(&klapic)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
|
||||
}
|
||||
|
@ -1545,6 +1606,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let mut kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
|
||||
let succ = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_msrs(&mut kvm_msrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetMsrEntries(e.into()))?;
|
||||
|
||||
|
@ -1567,6 +1630,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let kvm_msrs: Vec<kvm_msr_entry> = msrs.iter().map(|e| (*e).into()).collect();
|
||||
let kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_msrs(&kvm_msrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into()))
|
||||
}
|
||||
|
@ -1577,6 +1642,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn get_mp_state(&self) -> cpu::Result<MpState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_mp_state()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))?
|
||||
.into())
|
||||
|
@ -1587,6 +1654,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
fn set_mp_state(&self, mp_state: MpState) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_mp_state(mp_state.into())
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into()))
|
||||
}
|
||||
|
@ -1598,6 +1667,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
fn translate_gva(&self, gva: u64, _flags: u64) -> cpu::Result<(u64, u32)> {
|
||||
let tr = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.translate_gva(gva)
|
||||
.map_err(|e| cpu::HypervisorCpuError::TranslateVirtualAddress(e.into()))?;
|
||||
// tr.valid is set if the GVA is mapped to valid GPA.
|
||||
|
@ -1614,7 +1685,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
/// Triggers the running of the current virtual CPU returning an exit reason.
|
||||
///
|
||||
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
|
||||
match self.fd.run() {
|
||||
match self.fd.lock().unwrap().run() {
|
||||
Ok(run) => match run {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoIn(addr, data) => {
|
||||
|
@ -1625,7 +1696,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::IoIn(addr, data))
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoOut(addr, data) => {
|
||||
|
@ -1636,7 +1707,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::IoOut(addr, data))
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoapicEoi(vector) => Ok(cpu::VmExit::IoapicEoi(vector)),
|
||||
|
@ -1669,7 +1740,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::MmioRead(addr, data))
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
VcpuExit::MmioWrite(addr, data) => {
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
|
@ -1679,7 +1750,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::MmioWrite(addr, data))
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
VcpuExit::Hyperv => Ok(cpu::VmExit::Hyperv),
|
||||
#[cfg(feature = "tdx")]
|
||||
|
@ -1708,7 +1779,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
/// potential soft lockups when being resumed.
|
||||
///
|
||||
fn notify_guest_clock_paused(&self) -> cpu::Result<()> {
|
||||
if let Err(e) = self.fd.kvmclock_ctrl() {
|
||||
if let Err(e) = self.fd.lock().unwrap().kvmclock_ctrl() {
|
||||
// Linux kernel returns -EINVAL if the PV clock isn't yet initialised
|
||||
// which could be because we're still in firmware or the guest doesn't
|
||||
// use KVM clock.
|
||||
|
@ -1770,6 +1841,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
}
|
||||
}
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_guest_debug(&dbg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))
|
||||
}
|
||||
|
@ -1777,6 +1850,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
#[cfg(target_arch = "aarch64")]
|
||||
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.vcpu_init(kvi)
|
||||
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
|
||||
}
|
||||
|
@ -1788,6 +1863,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_reg_list(reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
|
||||
}
|
||||
|
@ -1820,6 +1897,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
| KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(id, &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
|
||||
Ok(u64::from_le_bytes(bytes))
|
||||
|
@ -1847,6 +1926,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
// Get the register index of the PSTATE (Processor State) register.
|
||||
let pstate = offset_of!(user_pt_regs, pstate) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
|
||||
&PSTATE_FAULT_BITS_64.to_le_bytes(),
|
||||
|
@ -1858,6 +1939,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
// Setting the PC (Processor Counter) to the current program address (kernel address).
|
||||
let pc = offset_of!(user_pt_regs, pc) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, pc),
|
||||
&boot_ip.to_le_bytes(),
|
||||
|
@ -1870,6 +1953,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
|
||||
let regs0 = offset_of!(user_pt_regs, regs) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
||||
&fdt_start.to_le_bytes(),
|
||||
|
@ -2021,6 +2106,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
let mut sys_regs: Vec<Register> = Vec::new();
|
||||
let mut reg_list = RegList::new(500).unwrap();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_reg_list(&mut reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
||||
|
||||
|
@ -2039,6 +2126,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
for index in indices.iter() {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(*index, &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
|
||||
sys_regs.push(kvm_bindings::kvm_one_reg {
|
||||
|
@ -2153,6 +2242,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
// Set system registers
|
||||
for reg in &state.sys_regs {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(reg.id, ®.addr.to_le_bytes())
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
|
||||
}
|
||||
|
@ -2167,15 +2258,20 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn tdx_init(&self, hob_address: u64) -> cpu::Result<()> {
|
||||
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
|
||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||
tdx_command(
|
||||
&self.fd.lock().unwrap().as_raw_fd(),
|
||||
TdxCommand::InitVcpu,
|
||||
0,
|
||||
hob_address,
|
||||
)
|
||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the "immediate_exit" state
|
||||
///
|
||||
fn set_immediate_exit(&self, exit: bool) {
|
||||
self.fd.set_kvm_immediate_exit(exit.into());
|
||||
self.fd.lock().unwrap().set_kvm_immediate_exit(exit.into());
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -2183,7 +2279,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn get_tdx_exit_details(&mut self) -> cpu::Result<TdxExitDetails> {
|
||||
let kvm_run = self.fd.get_kvm_run();
|
||||
let mut fd = self.fd.as_ref().lock().unwrap();
|
||||
let kvm_run = fd.get_kvm_run();
|
||||
// SAFETY: accessing a union field in a valid structure
|
||||
let tdx_vmcall = unsafe {
|
||||
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
|
||||
|
@ -2212,7 +2309,8 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn set_tdx_status(&mut self, status: TdxExitStatus) {
|
||||
let kvm_run = self.fd.get_kvm_run();
|
||||
let mut fd = self.fd.as_ref().lock().unwrap();
|
||||
let kvm_run = fd.get_kvm_run();
|
||||
// SAFETY: accessing a union field in a valid structure
|
||||
let tdx_vmcall = unsafe {
|
||||
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
|
||||
|
@ -2261,7 +2359,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
addr: 0x0,
|
||||
flags: 0,
|
||||
};
|
||||
self.fd.has_device_attr(&cpu_attr).is_ok()
|
||||
self.fd.lock().unwrap().has_device_attr(&cpu_attr).is_ok()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
|
@ -2279,9 +2377,13 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
flags: 0,
|
||||
};
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_device_attr(&cpu_attr_irq)
|
||||
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)?;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_device_attr(&cpu_attr)
|
||||
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)
|
||||
}
|
||||
|
@ -2291,7 +2393,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
/// Get the frequency of the TSC if available
|
||||
///
|
||||
fn tsc_khz(&self) -> cpu::Result<Option<u32>> {
|
||||
match self.fd.get_tsc_khz() {
|
||||
match self.fd.lock().unwrap().get_tsc_khz() {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(None)
|
||||
|
@ -2308,7 +2410,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
/// Set the frequency of the TSC if available
|
||||
///
|
||||
fn set_tsc_khz(&self, freq: u32) -> cpu::Result<()> {
|
||||
match self.fd.set_tsc_khz(freq) {
|
||||
match self.fd.lock().unwrap().set_tsc_khz(freq) {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(())
|
||||
|
@ -2325,7 +2427,7 @@ impl cpu::Vcpu for KvmVcpu {
|
|||
/// Trigger NMI interrupt
|
||||
///
|
||||
fn nmi(&self) -> cpu::Result<()> {
|
||||
match self.fd.nmi() {
|
||||
match self.fd.lock().unwrap().nmi() {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(())
|
||||
|
@ -2346,6 +2448,8 @@ impl KvmVcpu {
|
|||
fn get_xsave(&self) -> cpu::Result<XsaveState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_xsave()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))?
|
||||
.into())
|
||||
|
@ -2358,6 +2462,8 @@ impl KvmVcpu {
|
|||
fn set_xsave(&self, xsave: &XsaveState) -> cpu::Result<()> {
|
||||
let xsave: kvm_bindings::kvm_xsave = (*xsave).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_xsave(&xsave)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
||||
}
|
||||
|
@ -2368,6 +2474,8 @@ impl KvmVcpu {
|
|||
///
|
||||
fn get_xcrs(&self) -> cpu::Result<ExtendedControlRegisters> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_xcrs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
|
||||
}
|
||||
|
@ -2378,6 +2486,8 @@ impl KvmVcpu {
|
|||
///
|
||||
fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_xcrs(xcrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
|
||||
}
|
||||
|
@ -2389,6 +2499,8 @@ impl KvmVcpu {
|
|||
///
|
||||
fn get_vcpu_events(&self) -> cpu::Result<VcpuEvents> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_vcpu_events()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
|
||||
}
|
||||
|
@ -2400,6 +2512,8 @@ impl KvmVcpu {
|
|||
///
|
||||
fn set_vcpu_events(&self, events: &VcpuEvents) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_vcpu_events(events)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ pub enum ClockData {
|
|||
#[cfg(feature = "kvm")]
|
||||
Kvm(kvm_bindings::kvm_clock_data),
|
||||
#[cfg(feature = "mshv")]
|
||||
Mshv, /* MSHV does not support ClockData yet */
|
||||
Mshv(mshv::MshvClockData),
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::hypervisor;
|
|||
use crate::vec_with_array_field;
|
||||
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
||||
use crate::HypervisorType;
|
||||
pub use mshv_bindings::*;
|
||||
use mshv_bindings::*;
|
||||
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
@ -92,6 +92,25 @@ impl From<mshv_user_mem_region> for UserMemoryRegion {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl From<MshvClockData> for ClockData {
|
||||
fn from(d: MshvClockData) -> Self {
|
||||
ClockData::Mshv(d)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl From<ClockData> for MshvClockData {
|
||||
fn from(ms: ClockData) -> Self {
|
||||
match ms {
|
||||
ClockData::Mshv(s) => s,
|
||||
/* Needed in case other hypervisors are enabled */
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => unreachable!("MSHV clock data is not valid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UserMemoryRegion> for mshv_user_mem_region {
|
||||
fn from(region: UserMemoryRegion) -> Self {
|
||||
let mut flags: u32 = 0;
|
||||
|
@ -1280,15 +1299,13 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
/// Set CPU state for x86_64 guest.
|
||||
///
|
||||
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
||||
let state: VcpuMshvState = state.clone().into();
|
||||
let mut state: VcpuMshvState = state.clone().into();
|
||||
self.set_msrs(&state.msrs)?;
|
||||
self.set_vcpu_events(&state.vcpu_events)?;
|
||||
self.set_regs(&state.regs.into())?;
|
||||
self.set_sregs(&state.sregs.into())?;
|
||||
self.set_fpu(&state.fpu)?;
|
||||
self.set_xcrs(&state.xcrs)?;
|
||||
self.set_lapic(&state.lapic)?;
|
||||
self.set_xsave(&state.xsave)?;
|
||||
// These registers are global and needed to be set only for first VCPU
|
||||
// as Microsoft Hypervisor allows setting this regsier for only one VCPU
|
||||
if self.vp_index == 0 {
|
||||
|
@ -1299,6 +1316,9 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
self.fd
|
||||
.set_debug_regs(&state.dbg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
|
||||
self.fd
|
||||
.set_all_vp_state_components(&mut state.vp_states)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetAllVpStateComponents(e.into()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1322,8 +1342,6 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
let vcpu_events = self.get_vcpu_events()?;
|
||||
let mut msrs = self.msrs.clone();
|
||||
self.get_msrs(&mut msrs)?;
|
||||
let lapic = self.get_lapic()?;
|
||||
let xsave = self.get_xsave()?;
|
||||
let misc = self
|
||||
.fd
|
||||
.get_misc_regs()
|
||||
|
@ -1332,6 +1350,10 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
.fd
|
||||
.get_debug_regs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetDebugRegs(e.into()))?;
|
||||
let vp_states = self
|
||||
.fd
|
||||
.get_all_vp_state_components()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetAllVpStateComponents(e.into()))?;
|
||||
|
||||
Ok(VcpuMshvState {
|
||||
msrs,
|
||||
|
@ -1340,10 +1362,9 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
sregs: sregs.into(),
|
||||
fpu,
|
||||
xcrs,
|
||||
lapic,
|
||||
dbg,
|
||||
xsave,
|
||||
misc,
|
||||
vp_states,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
@ -1425,26 +1446,6 @@ impl cpu::Vcpu for MshvVcpu {
|
|||
}
|
||||
|
||||
impl MshvVcpu {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that returns the vcpu's current "xsave struct".
|
||||
///
|
||||
fn get_xsave(&self) -> cpu::Result<Xsave> {
|
||||
self.fd
|
||||
.get_xsave()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that sets the vcpu's current "xsave struct".
|
||||
///
|
||||
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.set_xsave(xsave)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that returns the vcpu's current "xcrs".
|
||||
|
@ -1948,13 +1949,23 @@ impl vm::Vm for MshvVm {
|
|||
/// Retrieve guest clock.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn get_clock(&self) -> vm::Result<ClockData> {
|
||||
Ok(ClockData::Mshv)
|
||||
let val = self
|
||||
.fd
|
||||
.get_partition_property(hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME)
|
||||
.map_err(|e| vm::HypervisorVmError::GetClock(e.into()))?;
|
||||
Ok(MshvClockData { ref_time: val }.into())
|
||||
}
|
||||
|
||||
/// Set guest clock.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
|
||||
Ok(())
|
||||
fn set_clock(&self, data: &ClockData) -> vm::Result<()> {
|
||||
let data: MshvClockData = (*data).into();
|
||||
self.fd
|
||||
.set_partition_property(
|
||||
hv_partition_property_code_HV_PARTITION_PROPERTY_REFERENCE_TIME,
|
||||
data.ref_time,
|
||||
)
|
||||
.map_err(|e| vm::HypervisorVmError::SetClock(e.into()))
|
||||
}
|
||||
|
||||
/// Downcast to the underlying MshvVm type
|
||||
|
|
|
@ -19,10 +19,10 @@ use std::fmt;
|
|||
///
|
||||
pub use {
|
||||
mshv_bindings::hv_cpuid_entry, mshv_bindings::mshv_user_mem_region as MemoryRegion,
|
||||
mshv_bindings::msr_entry, mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
||||
mshv_bindings::FloatingPointUnit, mshv_bindings::LapicState as MshvLapicState,
|
||||
mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList,
|
||||
mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
|
||||
mshv_bindings::msr_entry, mshv_bindings::AllVpStateComponents, mshv_bindings::CpuId,
|
||||
mshv_bindings::DebugRegisters, mshv_bindings::FloatingPointUnit,
|
||||
mshv_bindings::LapicState as MshvLapicState, mshv_bindings::MiscRegs as MiscRegisters,
|
||||
mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
|
||||
mshv_bindings::SegmentRegister as MshvSegmentRegister,
|
||||
mshv_bindings::SpecialRegisters as MshvSpecialRegisters,
|
||||
mshv_bindings::StandardRegisters as MshvStandardRegisters, mshv_bindings::SuspendRegisters,
|
||||
|
@ -38,10 +38,14 @@ pub struct VcpuMshvState {
|
|||
pub sregs: MshvSpecialRegisters,
|
||||
pub fpu: FpuState,
|
||||
pub xcrs: ExtendedControlRegisters,
|
||||
pub lapic: LapicState,
|
||||
pub dbg: DebugRegisters,
|
||||
pub xsave: Xsave,
|
||||
pub misc: MiscRegisters,
|
||||
pub vp_states: AllVpStateComponents,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MshvClockData {
|
||||
pub ref_time: u64,
|
||||
}
|
||||
|
||||
impl fmt::Display for VcpuMshvState {
|
||||
|
@ -53,7 +57,7 @@ impl fmt::Display for VcpuMshvState {
|
|||
msr_entries[i][1] = entry.data;
|
||||
msr_entries[i][0] = entry.index as u64;
|
||||
}
|
||||
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- Local APIC: {:?} --- DBG: {:?} --- Xsave: {:?}",
|
||||
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- DBG: {:?} --- VP States: {:?}",
|
||||
msr_entries.len(),
|
||||
msr_entries,
|
||||
self.vcpu_events,
|
||||
|
@ -61,9 +65,8 @@ impl fmt::Display for VcpuMshvState {
|
|||
self.sregs,
|
||||
self.fpu,
|
||||
self.xcrs,
|
||||
self.lapic,
|
||||
self.dbg,
|
||||
self.xsave,
|
||||
self.vp_states,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,10 @@ libc = "0.2.153"
|
|||
log = "0.4.21"
|
||||
net_gen = { path = "../net_gen" }
|
||||
rate_limiter = { path = "../rate_limiter" }
|
||||
serde = "1.0.197"
|
||||
thiserror = "1.0.58"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
serde = {version = "1.0.197",features = ["derive"]}
|
||||
thiserror = "1.0.60"
|
||||
virtio-bindings = "0.2.2"
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright © 2024 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rustc-check-cfg=cfg(fuzzing)");
|
||||
}
|
|
@ -14,13 +14,13 @@ mod open_tap;
|
|||
mod queue_pair;
|
||||
mod tap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Error as IoError;
|
||||
use std::os::raw::c_uint;
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::{io, mem, net};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
|
||||
use virtio_bindings::virtio_net::{
|
||||
virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
|
||||
VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4,
|
||||
|
@ -45,7 +45,7 @@ pub enum Error {
|
|||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct VirtioNetConfig {
|
||||
pub mac: [u8; 6],
|
||||
pub status: u16,
|
||||
|
@ -67,7 +67,7 @@ fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
|
|||
sin_family: net_gen::AF_INET as u16,
|
||||
sin_port: 0,
|
||||
// SAFETY: ip_addr can be safely transmute to in_addr
|
||||
sin_addr: unsafe { mem::transmute(ip_addr.octets()) },
|
||||
sin_addr: unsafe { mem::transmute::<[u8; 4], net_gen::inn::in_addr>(ip_addr.octets()) },
|
||||
__pad: [0; 8usize],
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use super::{register_listener, unregister_listener, vnet_hdr_len, Tap};
|
||||
use crate::GuestMemoryMmap;
|
||||
use rate_limiter::{RateLimiter, TokenType};
|
||||
use std::io;
|
||||
use std::num::Wrapping;
|
||||
|
@ -12,6 +11,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
|||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use virtio_queue::{Queue, QueueOwnedT, QueueT};
|
||||
use vm_memory::bitmap::Bitmap;
|
||||
use vm_memory::{Bytes, GuestMemory};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
|
||||
|
@ -35,9 +35,9 @@ impl TxVirtio {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn process_desc_chain(
|
||||
pub fn process_desc_chain<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
tap: &Tap,
|
||||
queue: &mut Queue,
|
||||
rate_limiter: &mut Option<RateLimiter>,
|
||||
|
@ -161,9 +161,9 @@ impl RxVirtio {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn process_desc_chain(
|
||||
pub fn process_desc_chain<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
tap: &Tap,
|
||||
queue: &mut Queue,
|
||||
rate_limiter: &mut Option<RateLimiter>,
|
||||
|
@ -350,9 +350,9 @@ pub struct NetQueuePair {
|
|||
}
|
||||
|
||||
impl NetQueuePair {
|
||||
pub fn process_tx(
|
||||
pub fn process_tx<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
queue: &mut Queue,
|
||||
) -> Result<bool, NetQueuePairError> {
|
||||
let tx_tap_retry = self.tx.process_desc_chain(
|
||||
|
@ -400,9 +400,9 @@ impl NetQueuePair {
|
|||
.map_err(NetQueuePairError::QueueNeedsNotification)
|
||||
}
|
||||
|
||||
pub fn process_rx(
|
||||
pub fn process_rx<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
queue: &mut Queue,
|
||||
) -> Result<bool, NetQueuePairError> {
|
||||
self.rx_desc_avail = !self.rx.process_desc_chain(
|
||||
|
|
|
@ -21,9 +21,7 @@ vmm-sys-util = "0.12.1"
|
|||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
thiserror = "1.0.58"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
thiserror = "1.0.60"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
|
|
@ -409,7 +409,7 @@ impl BusDevice for PciConfigMmio {
|
|||
// Only allow reads to the register boundary.
|
||||
let start = offset as usize % 4;
|
||||
let end = start + data.len();
|
||||
if end > 4 || offset > u64::from(u32::max_value()) {
|
||||
if end > 4 || offset > u64::from(u32::MAX) {
|
||||
for d in data {
|
||||
*d = 0xff;
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ impl BusDevice for PciConfigMmio {
|
|||
}
|
||||
|
||||
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
||||
if offset > u64::from(u32::max_value()) {
|
||||
if offset > u64::from(u32::MAX) {
|
||||
return None;
|
||||
}
|
||||
self.config_space_write(offset as u32, offset % 4, data);
|
||||
|
|
|
@ -7,12 +7,11 @@
|
|||
use crate::device::BarReprogrammingParams;
|
||||
use crate::{MsixConfig, PciInterruptPin};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::PciBarType;
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
|
||||
// The number of 32bit registers in the config space, 4096 bytes.
|
||||
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
|
||||
|
@ -398,7 +397,7 @@ fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> {
|
|||
None
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Versionize)]
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
|
||||
struct PciBar {
|
||||
addr: u32,
|
||||
size: u32,
|
||||
|
@ -406,7 +405,7 @@ struct PciBar {
|
|||
r#type: Option<PciBarRegionType>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PciConfigurationState {
|
||||
registers: Vec<u32>,
|
||||
writable_bits: Vec<u32>,
|
||||
|
@ -418,8 +417,6 @@ pub struct PciConfigurationState {
|
|||
msix_cap_reg_idx: Option<usize>,
|
||||
}
|
||||
|
||||
impl VersionMapped for PciConfigurationState {}
|
||||
|
||||
/// Contains the configuration space of a PCI node.
|
||||
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
|
||||
/// The configuration space is accessed with DWORD reads and writes from the guest.
|
||||
|
@ -437,7 +434,7 @@ pub struct PciConfiguration {
|
|||
}
|
||||
|
||||
/// See pci_regs.h in kernel
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Versionize, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum PciBarRegionType {
|
||||
Memory32BitRegion = 0,
|
||||
IoRegion = 0x01,
|
||||
|
@ -746,7 +743,7 @@ impl PciConfiguration {
|
|||
.ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
|
||||
match config.region_type {
|
||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
|
||||
if end_addr > u64::from(u32::max_value()) {
|
||||
if end_addr > u64::from(u32::MAX) {
|
||||
return Err(Error::BarAddressInvalid(config.addr, config.size));
|
||||
}
|
||||
|
||||
|
@ -760,10 +757,6 @@ impl PciConfiguration {
|
|||
return Err(Error::BarInvalid64(bar_idx));
|
||||
}
|
||||
|
||||
if end_addr > u64::max_value() {
|
||||
return Err(Error::BarAddressInvalid(config.addr, config.size));
|
||||
}
|
||||
|
||||
if self.bars[bar_idx + 1].used {
|
||||
return Err(Error::BarInUse64(bar_idx));
|
||||
}
|
||||
|
@ -821,7 +814,7 @@ impl PciConfiguration {
|
|||
.checked_add(config.size - 1)
|
||||
.ok_or(Error::RomBarAddressInvalid(config.addr, config.size))?;
|
||||
|
||||
if end_addr > u64::from(u32::max_value()) {
|
||||
if end_addr > u64::from(u32::MAX) {
|
||||
return Err(Error::RomBarAddressInvalid(config.addr, config.size));
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1065,7 @@ impl Snapshottable for PciConfiguration {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,14 @@
|
|||
//
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
|
||||
// MSI control masks
|
||||
const MSI_CTL_ENABLE: u16 = 0x1;
|
||||
|
@ -47,7 +46,7 @@ pub enum Error {
|
|||
|
||||
pub const MSI_CONFIG_ID: &str = "msi_config";
|
||||
|
||||
#[derive(Clone, Copy, Default, Versionize)]
|
||||
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
|
||||
pub struct MsiCap {
|
||||
// Message Control Register
|
||||
// 0: MSI enable.
|
||||
|
@ -172,13 +171,11 @@ impl MsiCap {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MsiConfigState {
|
||||
cap: MsiCap,
|
||||
}
|
||||
|
||||
impl VersionMapped for MsiConfigState {}
|
||||
|
||||
pub struct MsiConfig {
|
||||
pub cap: MsiCap,
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
|
@ -294,6 +291,6 @@ impl Snapshottable for MsiConfig {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
|
||||
use crate::{PciCapability, PciCapabilityId};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::io;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_memory::ByteValued;
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
|
||||
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
|
||||
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
|
||||
|
@ -35,7 +35,7 @@ pub enum Error {
|
|||
UpdateInterruptRoute(io::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Versionize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct MsixTableEntry {
|
||||
pub msg_addr_lo: u32,
|
||||
pub msg_addr_hi: u32,
|
||||
|
@ -60,7 +60,7 @@ impl Default for MsixTableEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MsixConfigState {
|
||||
table_entries: Vec<MsixTableEntry>,
|
||||
pba_entries: Vec<u64>,
|
||||
|
@ -68,8 +68,6 @@ pub struct MsixConfigState {
|
|||
enabled: bool,
|
||||
}
|
||||
|
||||
impl VersionMapped for MsixConfigState {}
|
||||
|
||||
pub struct MsixConfig {
|
||||
pub table_entries: Vec<MsixTableEntry>,
|
||||
pub pba_entries: Vec<u64>,
|
||||
|
@ -436,13 +434,13 @@ impl Snapshottable for MsixConfig {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy, Default, Versionize)]
|
||||
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
|
||||
pub struct MsixCap {
|
||||
// Message Control Register
|
||||
// 10-0: MSI-X Table size
|
||||
|
|
|
@ -15,6 +15,7 @@ use anyhow::anyhow;
|
|||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use hypervisor::HypervisorVmError;
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io;
|
||||
|
@ -22,8 +23,6 @@ use std::os::unix::io::AsRawFd;
|
|||
use std::ptr::null_mut;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vfio_bindings::bindings::vfio::*;
|
||||
use vfio_ioctls::{
|
||||
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
|
||||
|
@ -38,9 +37,7 @@ use vm_device::interrupt::{
|
|||
};
|
||||
use vm_device::{BusDevice, Resource};
|
||||
use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub(crate) const VFIO_COMMON_ID: &str = "vfio_common";
|
||||
|
@ -95,7 +92,7 @@ enum InterruptUpdateAction {
|
|||
DisableMsix,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct IntxState {
|
||||
enabled: bool,
|
||||
}
|
||||
|
@ -105,7 +102,7 @@ pub(crate) struct VfioIntx {
|
|||
enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MsiState {
|
||||
cap: MsiCap,
|
||||
cap_offset: u32,
|
||||
|
@ -137,7 +134,7 @@ impl VfioMsi {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MsixState {
|
||||
cap: MsixCap,
|
||||
cap_offset: u32,
|
||||
|
@ -440,15 +437,13 @@ impl Vfio for VfioDeviceWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct VfioCommonState {
|
||||
intx_state: Option<IntxState>,
|
||||
msi_state: Option<MsiState>,
|
||||
msix_state: Option<MsixState>,
|
||||
}
|
||||
|
||||
impl VersionMapped for VfioCommonState {}
|
||||
|
||||
pub(crate) struct ConfigPatch {
|
||||
mask: u32,
|
||||
patch: u32,
|
||||
|
@ -476,13 +471,12 @@ impl VfioCommon {
|
|||
x_nv_gpudirect_clique: Option<u8>,
|
||||
) -> Result<Self, VfioPciError> {
|
||||
let pci_configuration_state =
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
|
||||
VfioPciError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let configuration = PciConfiguration::new(
|
||||
0,
|
||||
|
@ -515,7 +509,7 @@ impl VfioCommon {
|
|||
|
||||
let state: Option<VfioCommonState> = snapshot
|
||||
.as_ref()
|
||||
.map(|s| s.to_versioned_state())
|
||||
.map(|s| s.to_state())
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrieveVfioCommonState(anyhow!(
|
||||
|
@ -523,20 +517,20 @@ impl VfioCommon {
|
|||
e
|
||||
))
|
||||
})?;
|
||||
let msi_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSI_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
let msi_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), MSI_CONFIG_ID).map_err(|e| {
|
||||
VfioPciError::RetrieveMsiConfigState(anyhow!(
|
||||
"Failed to get MsiConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let msix_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrieveMsixConfigState(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let msix_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID).map_err(|e| {
|
||||
VfioPciError::RetrieveMsixConfigState(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
if let Some(state) = state.as_ref() {
|
||||
vfio_common.set_state(state, msi_state, msix_state)?;
|
||||
|
@ -1388,7 +1382,7 @@ impl Snapshottable for VfioCommon {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
let mut vfio_common_snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||
let mut vfio_common_snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
vfio_common_snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
|
||||
|
|
|
@ -11,7 +11,6 @@ use std::any::Any;
|
|||
use std::os::unix::prelude::AsRawFd;
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::u32;
|
||||
use thiserror::Error;
|
||||
use vfio_bindings::bindings::vfio::*;
|
||||
use vfio_ioctls::VfioIrq;
|
||||
|
|
|
@ -11,5 +11,5 @@ dirs = "5.0.1"
|
|||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.115"
|
||||
test_infra = { path = "../test_infra" }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
wait-timeout = "0.2.0"
|
||||
|
|
|
@ -7,5 +7,5 @@ edition = "2021"
|
|||
epoll = "4.3.3"
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
|
|
@ -367,7 +367,7 @@ pub(crate) mod tests {
|
|||
assert!(h.as_raw_fd() > 0);
|
||||
|
||||
// ops/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(h.consume(u64::max_value(), TokenType::Ops));
|
||||
assert!(h.consume(u64::MAX, TokenType::Ops));
|
||||
|
||||
// do full 1000 bytes
|
||||
assert!(h.consume(1000, TokenType::Bytes));
|
||||
|
@ -403,7 +403,7 @@ pub(crate) mod tests {
|
|||
assert!(h.as_raw_fd() > 0);
|
||||
|
||||
// bytes/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(h.consume(u64::max_value(), TokenType::Bytes));
|
||||
assert!(h.consume(u64::MAX, TokenType::Bytes));
|
||||
|
||||
// do full 1000 ops
|
||||
assert!(h.consume(1000, TokenType::Ops));
|
||||
|
|
|
@ -662,8 +662,8 @@ pub(crate) mod tests {
|
|||
// limiter should not be blocked
|
||||
assert!(!l.is_blocked());
|
||||
// limiter should be disabled so consume(whatever) should work
|
||||
assert!(l.consume(u64::max_value(), TokenType::Ops));
|
||||
assert!(l.consume(u64::max_value(), TokenType::Bytes));
|
||||
assert!(l.consume(u64::MAX, TokenType::Ops));
|
||||
assert!(l.consume(u64::MAX, TokenType::Bytes));
|
||||
// calling the handler without there having been an event should error
|
||||
assert!(l.event_handler().is_err());
|
||||
assert_eq!(
|
||||
|
@ -721,7 +721,7 @@ pub(crate) mod tests {
|
|||
assert!(l.as_raw_fd() > 0);
|
||||
|
||||
// ops/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(l.consume(u64::max_value(), TokenType::Ops));
|
||||
assert!(l.consume(u64::MAX, TokenType::Ops));
|
||||
|
||||
// do full 1000 bytes
|
||||
assert!(l.consume(1000, TokenType::Bytes));
|
||||
|
@ -754,7 +754,7 @@ pub(crate) mod tests {
|
|||
assert!(l.as_raw_fd() > 0);
|
||||
|
||||
// bytes/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(l.consume(u64::max_value(), TokenType::Bytes));
|
||||
assert!(l.consume(u64::MAX, TokenType::Bytes));
|
||||
|
||||
// do full 1000 ops
|
||||
assert!(l.consume(1000, TokenType::Ops));
|
||||
|
|
202
release-notes.md
202
release-notes.md
|
@ -1,3 +1,10 @@
|
|||
- [v39.0](#v390)
|
||||
- [Variable Sizing of PCI Apertures for Segments](#variable-sizing-of-pci-apertures-for-segments)
|
||||
- [Direct Booting with bzImages](#direct-booting-with-bzimages)
|
||||
- [Support for NVIDIA GPUDirect P2P Support](#support-for-nvidia-gpudirect-p2p-support)
|
||||
- [Guest NMI Injection Support](#guest-nmi-injection-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [v38.0](#v380)
|
||||
- [Group Rate Limiter on Block Devices](#group-rate-limiter-on-block-devices)
|
||||
- [CPU Pinning Support for Block Device Worker Thread](#cpu-pinning-support-for-block-device-worker-thread)
|
||||
|
@ -5,16 +12,16 @@
|
|||
- [New 'debug-console' Device](#new-debug-console-device)
|
||||
- [Improved VFIO Device Support](#improved-vfio-device-support)
|
||||
- [Extended CPU Affinity Support](#extended-cpu-affinity-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Contributors](#contributors-1)
|
||||
- [v37.0](#v370)
|
||||
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
|
||||
- [Multiple PCI segments Support for 32-bit VFIO devices](#multiple-pci-segments-support-for-32-bit-vfio-devices)
|
||||
- [Configurable Named TAP Devices](#configurable-named-tap-devices)
|
||||
- [TTY Output from Both Serial Device and Virtio Console](#tty-output-from-both-serial-device-and-virtio-console)
|
||||
- [Faster VM Restoration from Snapshots](#faster-vm-restoration-from-snapshots)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Contributors](#contributors-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Contributors](#contributors-2)
|
||||
- [v36.0](#v360)
|
||||
- [Command Line Changes](#command-line-changes)
|
||||
- [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli)
|
||||
|
@ -23,31 +30,31 @@
|
|||
- [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port)
|
||||
- [AIO Backend for Block Devices](#aio-backend-for-block-devices)
|
||||
- [Documentation Improvements](#documentation-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Contributors](#contributors-2)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Contributors](#contributors-3)
|
||||
- [v35.0](#v350)
|
||||
- [`virtio-vsock` Support for Linux Guest Kernel v6.3+](#virtio-vsock-support-for-linux-guest-kernel-v63)
|
||||
- [User Specified Serial Number for `virtio-block`](#user-specified-serial-number-for-virtio-block)
|
||||
- [vCPU TSC Frequency Included in Migration State](#vcpu-tsc-frequency-included-in-migration-state)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Contributors](#contributors-3)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Contributors](#contributors-4)
|
||||
- [v34.0](#v340)
|
||||
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
|
||||
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
|
||||
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
|
||||
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Contributors](#contributors-4)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Contributors](#contributors-5)
|
||||
- [v33.0](#v330)
|
||||
- [D-Bus based API](#d-bus-based-api)
|
||||
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Contributors](#contributors-5)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Contributors](#contributors-6)
|
||||
- [v32.0](#v320)
|
||||
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
||||
- [API Changes](#api-changes)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Contributors](#contributors-6)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Contributors](#contributors-7)
|
||||
- [v31.1](#v311)
|
||||
- [v31.0](#v310)
|
||||
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
||||
|
@ -55,15 +62,15 @@
|
|||
- [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-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Contributors](#contributors-7)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Contributors](#contributors-8)
|
||||
- [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-2)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Contributors](#contributors-8)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||
- [Contributors](#contributors-9)
|
||||
- [v28.2](#v282)
|
||||
- [v29.0](#v290)
|
||||
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
||||
|
@ -73,10 +80,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-9)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||
- [Removals](#removals)
|
||||
- [Deprecations](#deprecations)
|
||||
- [Contributors](#contributors-9)
|
||||
- [Contributors](#contributors-10)
|
||||
- [v28.1](#v281)
|
||||
- [v28.0](#v280)
|
||||
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
||||
|
@ -84,9 +91,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-10)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||
- [Removals](#removals-1)
|
||||
- [Contributors](#contributors-10)
|
||||
- [Contributors](#contributors-11)
|
||||
- [v27.0](#v270)
|
||||
- [Community Engagement](#community-engagement)
|
||||
- [Prebuilt Packages](#prebuilt-packages)
|
||||
|
@ -95,41 +102,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-11)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||
- [Deprecations](#deprecations-1)
|
||||
- [Contributors](#contributors-11)
|
||||
- [Contributors](#contributors-12)
|
||||
- [v26.0](#v260)
|
||||
- [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-12)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-13)
|
||||
- [Deprecations](#deprecations-2)
|
||||
- [Removals](#removals-2)
|
||||
- [Contributors](#contributors-12)
|
||||
- [Contributors](#contributors-13)
|
||||
- [v25.0](#v250)
|
||||
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
||||
- [VM "Coredump" Support](#vm-coredump-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-13)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-14)
|
||||
- [Removals](#removals-3)
|
||||
- [Contributors](#contributors-13)
|
||||
- [Contributors](#contributors-14)
|
||||
- [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-14)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-15)
|
||||
- [Notable Improvements](#notable-improvements)
|
||||
- [Deprecations](#deprecations-3)
|
||||
- [New on the Website](#new-on-the-website)
|
||||
- [Contributors](#contributors-14)
|
||||
- [Contributors](#contributors-15)
|
||||
- [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-15)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-16)
|
||||
- [Deprecations](#deprecations-4)
|
||||
- [Contributors](#contributors-15)
|
||||
- [Contributors](#contributors-16)
|
||||
- [v22.1](#v221)
|
||||
- [v22.0](#v220)
|
||||
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
||||
|
@ -140,13 +147,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-16)
|
||||
- [Contributors](#contributors-16)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-17)
|
||||
- [Contributors](#contributors-17)
|
||||
- [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-17)
|
||||
- [Contributors](#contributors-17)
|
||||
- [Notable Bug fixes](#notable-bug-fixes-18)
|
||||
- [Contributors](#contributors-18)
|
||||
- [v20.2](#v202)
|
||||
- [v20.1](#v201)
|
||||
- [v20.0](#v200)
|
||||
|
@ -155,8 +162,8 @@
|
|||
- [Improved VFIO support](#improved-vfio-support)
|
||||
- [Safer code](#safer-code)
|
||||
- [Extended documentation](#extended-documentation)
|
||||
- [Notable bug fixes](#notable-bug-fixes-18)
|
||||
- [Contributors](#contributors-18)
|
||||
- [Notable bug fixes](#notable-bug-fixes-19)
|
||||
- [Contributors](#contributors-19)
|
||||
- [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)
|
||||
|
@ -164,8 +171,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-19)
|
||||
- [Contributors](#contributors-19)
|
||||
- [Notable bug fixes](#notable-bug-fixes-20)
|
||||
- [Contributors](#contributors-20)
|
||||
- [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)
|
||||
|
@ -175,23 +182,23 @@
|
|||
- [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-20)
|
||||
- [Contributors](#contributors-20)
|
||||
- [Notable bug fixes](#notable-bug-fixes-21)
|
||||
- [Contributors](#contributors-21)
|
||||
- [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-21)
|
||||
- [Contributors](#contributors-21)
|
||||
- [Notable bug fixes](#notable-bug-fixes-22)
|
||||
- [Contributors](#contributors-22)
|
||||
- [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-22)
|
||||
- [Notable bug fixes](#notable-bug-fixes-23)
|
||||
- [Removed functionality](#removed-functionality)
|
||||
- [Contributors](#contributors-22)
|
||||
- [Contributors](#contributors-23)
|
||||
- [v15.0](#v150)
|
||||
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
||||
- [Network device rate limiting](#network-device-rate-limiting)
|
||||
|
@ -199,7 +206,7 @@
|
|||
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
||||
- [Bug fixes](#bug-fixes)
|
||||
- [Deprecations](#deprecations-5)
|
||||
- [Contributors](#contributors-23)
|
||||
- [Contributors](#contributors-24)
|
||||
- [v0.14.1](#v0141)
|
||||
- [v0.14.0](#v0140)
|
||||
- [Structured event monitoring](#structured-event-monitoring)
|
||||
|
@ -209,7 +216,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-24)
|
||||
- [Contributors](#contributors-25)
|
||||
- [v0.13.0](#v0130)
|
||||
- [Wider VFIO device support](#wider-vfio-device-support)
|
||||
- [Improved huge page support](#improved-huge-page-support)
|
||||
|
@ -217,13 +224,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-25)
|
||||
- [Contributors](#contributors-26)
|
||||
- [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-26)
|
||||
- [Contributors](#contributors-27)
|
||||
- [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)
|
||||
|
@ -235,15 +242,15 @@
|
|||
- [Default Log Level Changed](#default-log-level-changed)
|
||||
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
||||
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-23)
|
||||
- [Contributors](#contributors-27)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-24)
|
||||
- [Contributors](#contributors-28)
|
||||
- [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-24)
|
||||
- [Contributors](#contributors-28)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-25)
|
||||
- [Contributors](#contributors-29)
|
||||
- [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)
|
||||
|
@ -256,17 +263,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-25)
|
||||
- [Contributors](#contributors-29)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-26)
|
||||
- [Contributors](#contributors-30)
|
||||
- [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-26)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-27)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||
- [Contributors](#contributors-30)
|
||||
- [Contributors](#contributors-31)
|
||||
- [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)
|
||||
|
@ -276,14 +283,14 @@
|
|||
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
||||
- [Updated Distribution Support](#updated-distribution-support)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
||||
- [Contributors](#contributors-31)
|
||||
- [Contributors](#contributors-32)
|
||||
- [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-32)
|
||||
- [Contributors](#contributors-33)
|
||||
- [v0.5.1](#v051)
|
||||
- [v0.5.0](#v050)
|
||||
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
||||
|
@ -291,7 +298,7 @@
|
|||
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
||||
- [Development Tools](#development-tools)
|
||||
- [Kata Containers Integration](#kata-containers-integration)
|
||||
- [Contributors](#contributors-33)
|
||||
- [Contributors](#contributors-34)
|
||||
- [v0.4.0](#v040)
|
||||
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
||||
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
||||
|
@ -300,7 +307,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-34)
|
||||
- [Contributors](#contributors-35)
|
||||
- [v0.3.0](#v030)
|
||||
- [Block device offloading](#block-device-offloading)
|
||||
- [Network device backend](#network-device-backend)
|
||||
|
@ -327,6 +334,77 @@
|
|||
- [Unit testing](#unit-testing)
|
||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||
|
||||
# v39.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||
v39.0. The following user visible changes have been made:
|
||||
|
||||
### Variable Sizing of PCI Apertures for Segments
|
||||
|
||||
It is now possible to use `--pci-segment` to adjust the aperture size that
|
||||
devices 32-bit and 64-bit PCI device BARs will be allocated from. Previously
|
||||
the address space was equally distributed across all the segments which may
|
||||
leave insufficient space for devices that require a large 32-bit space. With
|
||||
this change the weighting per segment can be adjusted. (#6387)
|
||||
|
||||
### Direct Booting with bzImages
|
||||
|
||||
Support for directly booting Linux from bzImages has been added.(#6200)
|
||||
|
||||
### Support for NVIDIA GPUDirect P2P Support
|
||||
|
||||
The `x_nv_gpudirect_clique` option was added to `--device` to allow the
|
||||
configuration of device P2P support with NVIDIA GPUs. (#6235)
|
||||
|
||||
### Guest NMI Injection Support
|
||||
|
||||
A new API endpoint and `ch-remote` option added for injecting an NMI into the
|
||||
guest. (#6047)
|
||||
|
||||
### Notable Bug Fixes
|
||||
|
||||
* Workaround for kernel bug affecting guest IRQ masking on AMD (#6353)
|
||||
* Correctly cleanup `sigwinch_listener` process (#6208)
|
||||
* Graceful shutdown of HTTP API thread (#6248, #6247)
|
||||
* Fix `queue_affinity` option in OpenAPI metadata (#6268)
|
||||
* Fix documentation to indicate only stream mode is supported by `virtio-vsock`
|
||||
(#6306)
|
||||
* Fix `virtio-fs` tag validation (#6358, #6359)
|
||||
* Add missing `pvpanic` device to OpenAPI metadata (#6372)
|
||||
* Fixes for nested virtualization with VFIO devices (#6110, #6298, #6297,
|
||||
#6319)
|
||||
* Fix for backing file for `virtio-mem` regions with snapshot/restore (#6337,
|
||||
#6338)
|
||||
* Explicitly mark FDs used for network devices as invalid across
|
||||
snapshot/restore (#6332, #6286)
|
||||
* Improve `event-monitor` events around reboot (#6277, #6274)
|
||||
* Fix potential deadlock around paused devices during live migration (#6293)
|
||||
* Fix panic when running `ch-remote` with no subcommand (#6230)
|
||||
* Fix hotplug of `virtio` devices after snapshot/restore and live migration
|
||||
(#6326, #6265)
|
||||
|
||||
### Contributors
|
||||
|
||||
Many thanks to everyone who has contributed to our release:
|
||||
|
||||
* Alexandru Matei <alexandru.matei@uipath.com>
|
||||
* Andrew Carp <acarp@crusoeenergy.com>
|
||||
* Bo Chen <chen.bo@intel.com>
|
||||
* Bouke van der Bijl <i@bou.ke>
|
||||
* Chris Webb <chris@arachsys.com>
|
||||
* Jinank Jain <jinankjain@microsoft.com>
|
||||
* Lucas Jacques <contact@lucasjacques.com>
|
||||
* Muminul Islam <muislam@microsoft.com>
|
||||
* Nuno Das Neves <nudasnev@microsoft.com>
|
||||
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||
* Rob Bradford <rbradford@rivosinc.com>
|
||||
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||
* Stefan Nuernberger <stefan.nuernberger@cyberus-technology.de>
|
||||
* Thomas Barrett <tbarrett@crusoeenergy.com>
|
||||
* Wei Liu <liuwe@microsoft.com>
|
||||
* Yi Wang <foxywang@tencent.com>
|
||||
|
||||
# v38.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
FROM ubuntu:22.04 as dev
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG RUST_TOOLCHAIN="1.74.1"
|
||||
ARG RUST_TOOLCHAIN="1.77.0"
|
||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||
|
|
|
@ -9,7 +9,7 @@ CLI_NAME="Cloud Hypervisor"
|
|||
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
|
||||
|
||||
# Needs to match explicit version in docker-image.yaml workflow
|
||||
CTR_IMAGE_VERSION="20240407-0"
|
||||
CTR_IMAGE_VERSION="20240507-0"
|
||||
: "${CTR_IMAGE:=${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}}"
|
||||
|
||||
DOCKER_RUNTIME="docker"
|
||||
|
|
|
@ -134,7 +134,7 @@ update_workloads() {
|
|||
popd || exit
|
||||
|
||||
# Download Cloud Hypervisor binary from its last stable release
|
||||
LAST_RELEASE_VERSION="v36.0"
|
||||
LAST_RELEASE_VERSION="v39.0"
|
||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
|
||||
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
|
||||
pushd "$WORKLOADS_DIR" || exit
|
||||
|
|
|
@ -45,7 +45,7 @@ fi
|
|||
popd || exit
|
||||
|
||||
# Download Cloud Hypervisor binary from its last stable release
|
||||
LAST_RELEASE_VERSION="v36.0"
|
||||
LAST_RELEASE_VERSION="v39.0"
|
||||
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
|
||||
CH_RELEASE_NAME="cloud-hypervisor-static"
|
||||
pushd "$WORKLOADS_DIR" || exit
|
||||
|
|
|
@ -355,6 +355,13 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
|
|||
.num_args(1..)
|
||||
.group("vm-config"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("pci-segment")
|
||||
.long("pci-segment")
|
||||
.help(config::PciSegmentConfig::SYNTAX)
|
||||
.num_args(1..)
|
||||
.group("vm-config"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("watchdog")
|
||||
.long("watchdog")
|
||||
|
@ -934,6 +941,7 @@ mod unit_tests {
|
|||
watchdog: false,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb: false,
|
||||
pci_segments: None,
|
||||
platform: None,
|
||||
tpm: None,
|
||||
preserved_fds: None,
|
||||
|
|
|
@ -2344,7 +2344,10 @@ fn make_guest_panic(guest: &Guest) {
|
|||
}
|
||||
|
||||
mod common_parallel {
|
||||
use std::{fs::OpenOptions, io::SeekFrom};
|
||||
use std::{
|
||||
fs::{remove_dir_all, OpenOptions},
|
||||
io::SeekFrom,
|
||||
};
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
@ -6012,10 +6015,10 @@ mod common_parallel {
|
|||
"id={},tap=,mac={},ip={},mask=255.255.255.0",
|
||||
net_id, guest.network.guest_mac, guest.network.host_ip
|
||||
);
|
||||
let mut mem_params = "size=4G";
|
||||
let mut mem_params = "size=2G";
|
||||
|
||||
if use_hotplug {
|
||||
mem_params = "size=4G,hotplug_method=virtio-mem,hotplug_size=32G"
|
||||
mem_params = "size=2G,hotplug_method=virtio-mem,hotplug_size=32G"
|
||||
}
|
||||
|
||||
let cloudinit_params = format!(
|
||||
|
@ -6059,7 +6062,7 @@ mod common_parallel {
|
|||
// Check the number of vCPUs
|
||||
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4);
|
||||
// Check the guest RAM
|
||||
assert!(guest.get_total_memory().unwrap_or_default() > 3_840_000);
|
||||
assert!(guest.get_total_memory().unwrap_or_default() > 1_920_000);
|
||||
if use_hotplug {
|
||||
// Increase guest RAM with virtio-mem
|
||||
resize_command(
|
||||
|
@ -6229,6 +6232,9 @@ mod common_parallel {
|
|||
&event_path_restored
|
||||
));
|
||||
|
||||
// Remove the snapshot dir
|
||||
let _ = remove_dir_all(snapshot_dir.as_str());
|
||||
|
||||
let r = std::panic::catch_unwind(|| {
|
||||
// Resume the VM
|
||||
assert!(remote_command(&api_socket_restored, "resume", None));
|
||||
|
@ -6257,7 +6263,7 @@ mod common_parallel {
|
|||
assert_eq!(guest.get_cpu_count().unwrap_or_default(), 4);
|
||||
let total_memory = guest.get_total_memory().unwrap_or_default();
|
||||
if !use_hotplug {
|
||||
assert!(guest.get_total_memory().unwrap_or_default() > 3_840_000);
|
||||
assert!(total_memory > 1_920_000);
|
||||
} else {
|
||||
assert!(total_memory > 4_800_000);
|
||||
assert!(total_memory < 5_760_000);
|
||||
|
@ -9718,18 +9724,6 @@ mod live_migration {
|
|||
_test_live_migration(false, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_migration_numa() {
|
||||
_test_live_migration_numa(false, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_migration_numa_local() {
|
||||
_test_live_migration_numa(false, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_live_migration_watchdog() {
|
||||
_test_live_migration_watchdog(false, false)
|
||||
|
@ -9740,6 +9734,32 @@ mod live_migration {
|
|||
_test_live_migration_watchdog(false, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_live_upgrade_basic() {
|
||||
_test_live_migration(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_live_upgrade_local() {
|
||||
_test_live_migration(true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_live_upgrade_watchdog() {
|
||||
_test_live_migration_watchdog(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_live_upgrade_watchdog_local() {
|
||||
_test_live_migration_watchdog(true, true)
|
||||
}
|
||||
}
|
||||
|
||||
mod live_migration_sequential {
|
||||
use super::*;
|
||||
|
||||
// NUMA & baalloon live migration tests are large so run sequentially
|
||||
|
||||
#[test]
|
||||
fn test_live_migration_balloon() {
|
||||
_test_live_migration_balloon(false, false)
|
||||
|
@ -9751,61 +9771,39 @@ mod live_migration {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_basic() {
|
||||
_test_live_migration(true, false)
|
||||
fn test_live_upgrade_balloon() {
|
||||
_test_live_migration_balloon(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_local() {
|
||||
_test_live_migration(true, true)
|
||||
fn test_live_upgrade_balloon_local() {
|
||||
_test_live_migration_balloon(true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_migration_numa() {
|
||||
_test_live_migration_numa(false, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_migration_numa_local() {
|
||||
_test_live_migration_numa(false, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_upgrade_numa() {
|
||||
_test_live_migration_numa(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
fn test_live_upgrade_numa_local() {
|
||||
_test_live_migration_numa(true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_watchdog() {
|
||||
_test_live_migration_watchdog(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_watchdog_local() {
|
||||
_test_live_migration_watchdog(true, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_balloon() {
|
||||
_test_live_migration_balloon(true, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "See #6134"]
|
||||
fn test_live_upgrade_balloon_local() {
|
||||
_test_live_migration_balloon(true, true)
|
||||
}
|
||||
}
|
||||
|
||||
mod live_migration_sequential {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(not(feature = "mshv"))]
|
||||
use super::*;
|
||||
|
||||
// Require to run ovs-dpdk tests sequentially because they rely on the same ovs-dpdk setup
|
||||
#[test]
|
||||
#[ignore = "See #5532"]
|
||||
|
|
|
@ -13,9 +13,9 @@ epoll = "4.3.3"
|
|||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
option_parser = { path = "../option_parser" }
|
||||
vhost = { version = "0.10.0", features = ["vhost-user-backend"] }
|
||||
vhost-user-backend = "0.13.1"
|
||||
vhost = { version = "0.11.0", features = ["vhost-user-backend"] }
|
||||
vhost-user-backend = "0.15.0"
|
||||
virtio-bindings = "0.2.2"
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = "0.14.1"
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
|
|
@ -32,16 +32,18 @@ use std::time::Instant;
|
|||
use std::{convert, error, fmt, io};
|
||||
use vhost::vhost_user::message::*;
|
||||
use vhost::vhost_user::Listener;
|
||||
use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringState, VringT};
|
||||
use vhost_user_backend::{
|
||||
bitmap::BitmapMmapRegion, VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringState, VringT,
|
||||
};
|
||||
use virtio_bindings::virtio_blk::*;
|
||||
use virtio_bindings::virtio_config::VIRTIO_F_VERSION_1;
|
||||
use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
||||
use virtio_queue::QueueT;
|
||||
use vm_memory::GuestAddressSpace;
|
||||
use vm_memory::{bitmap::AtomicBitmap, ByteValued, Bytes, GuestMemoryAtomic};
|
||||
use vm_memory::{ByteValued, Bytes, GuestMemoryAtomic};
|
||||
use vmm_sys_util::{epoll::EventSet, eventfd::EventFd};
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<BitmapMmapRegion>;
|
||||
|
||||
const SECTOR_SHIFT: u8 = 9;
|
||||
const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
|
||||
|
@ -300,7 +302,7 @@ impl VhostUserBlkBackend {
|
|||
}
|
||||
|
||||
impl VhostUserBackendMut for VhostUserBlkBackend {
|
||||
type Bitmap = AtomicBitmap;
|
||||
type Bitmap = BitmapMmapRegion;
|
||||
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
|
||||
|
||||
fn num_queues(&self) -> usize {
|
||||
|
|
|
@ -13,8 +13,8 @@ libc = "0.2.153"
|
|||
log = "0.4.21"
|
||||
net_util = { path = "../net_util" }
|
||||
option_parser = { path = "../option_parser" }
|
||||
vhost = { version = "0.10.0", features = ["vhost-user-backend"] }
|
||||
vhost-user-backend = "0.13.1"
|
||||
vhost = { version = "0.11.0", features = ["vhost-user-backend"] }
|
||||
vhost-user-backend = "0.15.0"
|
||||
virtio-bindings = "0.2.2"
|
||||
vm-memory = "0.14.1"
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
|
|
@ -22,14 +22,15 @@ use std::process;
|
|||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use vhost::vhost_user::message::*;
|
||||
use vhost::vhost_user::Listener;
|
||||
use vhost_user_backend::bitmap::BitmapMmapRegion;
|
||||
use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringT};
|
||||
use virtio_bindings::virtio_config::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1};
|
||||
use virtio_bindings::virtio_net::*;
|
||||
use vm_memory::GuestAddressSpace;
|
||||
use vm_memory::{bitmap::AtomicBitmap, GuestMemoryAtomic};
|
||||
use vm_memory::GuestMemoryAtomic;
|
||||
use vmm_sys_util::{epoll::EventSet, eventfd::EventFd};
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<BitmapMmapRegion>;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
type VhostUserBackendResult<T> = std::result::Result<T, std::io::Error>;
|
||||
|
@ -158,7 +159,7 @@ impl VhostUserNetBackend {
|
|||
}
|
||||
|
||||
impl VhostUserBackendMut for VhostUserNetBackend {
|
||||
type Bitmap = AtomicBitmap;
|
||||
type Bitmap = BitmapMmapRegion;
|
||||
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>;
|
||||
|
||||
fn num_queues(&self) -> usize {
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
|
||||
[features]
|
||||
default = []
|
||||
sev_snp = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
|
@ -23,13 +24,12 @@ rate_limiter = { path = "../rate_limiter" }
|
|||
seccompiler = "0.4.0"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_json = "1.0.115"
|
||||
serde_with = { version = "3.7.0", default-features = false, features = ["macros"] }
|
||||
serial_buffer = { path = "../serial_buffer" }
|
||||
thiserror = "1.0.58"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vhost = { version = "0.10.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] }
|
||||
thiserror = "1.0.60"
|
||||
vhost = { version = "0.11.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] }
|
||||
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright © 2024 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rustc-check-cfg=cfg(fuzzing)");
|
||||
}
|
|
@ -22,23 +22,20 @@ use crate::{
|
|||
};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::{self, Write};
|
||||
use std::mem::size_of;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::result;
|
||||
use std::sync::{atomic::AtomicBool, Arc, Barrier};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_allocator::page_size::{align_page_size_down, get_page_size};
|
||||
use vm_memory::{
|
||||
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
|
||||
GuestMemoryError, GuestMemoryRegion,
|
||||
};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const QUEUE_SIZE: u16 = 128;
|
||||
|
@ -89,7 +86,7 @@ pub enum Error {
|
|||
|
||||
// Got from include/uapi/linux/virtio_balloon.h
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct VirtioBalloonConfig {
|
||||
// Number of pages host wants Guest to give up.
|
||||
num_pages: u32,
|
||||
|
@ -418,15 +415,13 @@ impl EpollHelperHandler for BalloonEpollHandler {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct BalloonState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
pub config: VirtioBalloonConfig,
|
||||
}
|
||||
|
||||
impl VersionMapped for BalloonState {}
|
||||
|
||||
// Virtio device for exposing entropy to the guest OS through virtio.
|
||||
pub struct Balloon {
|
||||
common: VirtioCommon,
|
||||
|
@ -672,7 +667,7 @@ impl Snapshottable for Balloon {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Balloon {}
|
||||
|
|
|
@ -25,6 +25,7 @@ use block::{
|
|||
use rate_limiter::group::{RateLimiterGroup, RateLimiterGroupHandle};
|
||||
use rate_limiter::TokenType;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
|
@ -37,13 +38,10 @@ use std::result;
|
|||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_bindings::virtio_blk::*;
|
||||
use virtio_bindings::virtio_config::*;
|
||||
use virtio_queue::{Queue, QueueOwnedT, QueueT};
|
||||
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryError};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -552,7 +550,7 @@ pub struct Block {
|
|||
queue_affinity: BTreeMap<u16, Vec<usize>>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct BlockState {
|
||||
pub disk_path: String,
|
||||
pub disk_nsectors: u64,
|
||||
|
@ -561,8 +559,6 @@ pub struct BlockState {
|
|||
pub config: VirtioBlockConfig,
|
||||
}
|
||||
|
||||
impl VersionMapped for BlockState {}
|
||||
|
||||
impl Block {
|
||||
/// Create a new virtio block device that operates on the given file.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -916,7 +912,7 @@ impl Snapshottable for Block {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Block {}
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::VirtioInterrupt;
|
|||
use anyhow::anyhow;
|
||||
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serial_buffer::SerialBuffer;
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
|
@ -25,11 +26,8 @@ use std::result;
|
|||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -67,7 +65,7 @@ enum Error {
|
|||
QueueAddUsed(virtio_queue::Error),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioConsoleConfig {
|
||||
cols: u16,
|
||||
|
@ -593,7 +591,7 @@ pub struct Console {
|
|||
exit_evt: EventFd,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ConsoleState {
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
|
@ -620,8 +618,6 @@ fn get_win_size(tty: &dyn AsRawFd) -> (u16, u16) {
|
|||
(ws.cols, ws.rows)
|
||||
}
|
||||
|
||||
impl VersionMapped for ConsoleState {}
|
||||
|
||||
impl Console {
|
||||
/// Create a new virtio console device
|
||||
pub fn new(
|
||||
|
@ -825,7 +821,7 @@ impl Snapshottable for Console {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Console {}
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::GuestMemoryMmap;
|
|||
use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::mem::size_of;
|
||||
|
@ -22,15 +23,12 @@ use std::result;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex, RwLock};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{DescriptorChain, Queue, QueueT};
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
use vm_memory::{
|
||||
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
|
||||
GuestMemoryError, GuestMemoryLoadGuard,
|
||||
};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -781,7 +779,7 @@ impl EpollHelperHandler for IommuEpollHandler {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Versionize)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
struct Mapping {
|
||||
gpa: u64,
|
||||
size: u64,
|
||||
|
@ -905,7 +903,7 @@ pub struct Iommu {
|
|||
type EndpointsState = Vec<(u32, u32)>;
|
||||
type DomainsState = Vec<(u32, (Vec<(u64, Mapping)>, bool))>;
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct IommuState {
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
|
@ -913,8 +911,6 @@ pub struct IommuState {
|
|||
domains: DomainsState,
|
||||
}
|
||||
|
||||
impl VersionMapped for IommuState {}
|
||||
|
||||
impl Iommu {
|
||||
pub fn new(
|
||||
id: String,
|
||||
|
@ -1154,7 +1150,7 @@ impl Snapshottable for Iommu {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Iommu {}
|
||||
|
|
|
@ -25,6 +25,7 @@ use crate::{GuestMemoryMmap, GuestRegionMmap};
|
|||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::mem::size_of;
|
||||
|
@ -34,8 +35,6 @@ use std::sync::atomic::AtomicBool;
|
|||
use std::sync::mpsc;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{DescriptorChain, Queue, QueueT};
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
use vm_memory::{
|
||||
|
@ -43,9 +42,7 @@ use vm_memory::{
|
|||
GuestMemoryError, GuestMemoryLoadGuard, GuestMemoryRegion,
|
||||
};
|
||||
use vm_migration::protocol::MemoryRangeTable;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const QUEUE_SIZE: u16 = 128;
|
||||
|
@ -170,7 +167,7 @@ struct VirtioMemResp {
|
|||
unsafe impl ByteValued for VirtioMemResp {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct VirtioMemConfig {
|
||||
// Block size and alignment. Cannot change.
|
||||
block_size: u64,
|
||||
|
@ -338,7 +335,7 @@ impl Request {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Versionize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct BlocksState {
|
||||
bitmap: Vec<bool>,
|
||||
}
|
||||
|
@ -688,7 +685,7 @@ pub enum VirtioMemMappingSource {
|
|||
Device(u32),
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MemState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -696,8 +693,6 @@ pub struct MemState {
|
|||
pub blocks_state: BlocksState,
|
||||
}
|
||||
|
||||
impl VersionMapped for MemState {}
|
||||
|
||||
pub struct Mem {
|
||||
common: VirtioCommon,
|
||||
id: String,
|
||||
|
@ -1013,7 +1008,7 @@ impl Snapshottable for Mem {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Mem {}
|
||||
|
|
|
@ -24,6 +24,7 @@ use net_util::{
|
|||
NetQueuePair, OpenTapError, RxVirtio, Tap, TapError, TxVirtio, VirtioNetConfig,
|
||||
};
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::num::Wrapping;
|
||||
|
@ -34,14 +35,11 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_bindings::virtio_config::*;
|
||||
use virtio_bindings::virtio_net::*;
|
||||
use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -423,7 +421,7 @@ pub struct Net {
|
|||
exit_evt: EventFd,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NetState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -431,8 +429,6 @@ pub struct NetState {
|
|||
pub queue_size: Vec<u16>,
|
||||
}
|
||||
|
||||
impl VersionMapped for NetState {}
|
||||
|
||||
impl Net {
|
||||
/// Create a new virtio network device with the given TAP interface.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -886,7 +882,7 @@ impl Snapshottable for Net {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl Transportable for Net {}
|
||||
|
|
|
@ -18,6 +18,7 @@ use crate::{GuestMemoryMmap, MmapRegion};
|
|||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::mem::size_of;
|
||||
|
@ -26,14 +27,11 @@ use std::result;
|
|||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{DescriptorChain, Queue, QueueT};
|
||||
use vm_memory::{
|
||||
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
|
||||
GuestMemoryError, GuestMemoryLoadGuard,
|
||||
};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -48,7 +46,7 @@ const VIRTIO_PMEM_RESP_TYPE_EIO: u32 = 1;
|
|||
// New descriptors are pending on the virtio queue.
|
||||
const QUEUE_AVAIL_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
struct VirtioPmemConfig {
|
||||
start: u64,
|
||||
|
@ -279,15 +277,13 @@ pub struct Pmem {
|
|||
_region: MmapRegion,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PmemState {
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
config: VirtioPmemConfig,
|
||||
}
|
||||
|
||||
impl VersionMapped for PmemState {}
|
||||
|
||||
impl Pmem {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
|
@ -468,7 +464,7 @@ impl Snapshottable for Pmem {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::GuestMemoryMmap;
|
|||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
@ -23,11 +24,8 @@ use std::result;
|
|||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
@ -160,14 +158,12 @@ pub struct Rng {
|
|||
exit_evt: EventFd,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct RngState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
}
|
||||
|
||||
impl VersionMapped for RngState {}
|
||||
|
||||
impl Rng {
|
||||
/// Create a new virtio rng device that gets random data from /dev/urandom.
|
||||
pub fn new(
|
||||
|
@ -326,7 +322,7 @@ impl Snapshottable for Rng {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,17 +8,16 @@
|
|||
|
||||
use crate::VirtioDevice;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
|
||||
pub const VIRTIO_PCI_COMMON_CONFIG_ID: &str = "virtio_pci_common_config";
|
||||
|
||||
#[derive(Clone, Versionize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct VirtioPciCommonConfigState {
|
||||
pub driver_status: u8,
|
||||
pub config_generation: u8,
|
||||
|
@ -29,8 +28,6 @@ pub struct VirtioPciCommonConfigState {
|
|||
pub msix_queues: Vec<u16>,
|
||||
}
|
||||
|
||||
impl VersionMapped for VirtioPciCommonConfigState {}
|
||||
|
||||
/// Contains the data for reading and writing the common configuration structure of a virtio PCI
|
||||
/// device.
|
||||
///
|
||||
|
@ -321,7 +318,7 @@ impl Snapshottable for VirtioPciCommonConfig {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ use pci::{
|
|||
PciCapability, PciCapabilityId, PciClassCode, PciConfiguration, PciDevice, PciDeviceError,
|
||||
PciHeaderType, PciMassStorageSubclass, PciNetworkControllerSubclass, PciSubclass,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
|
@ -27,8 +28,6 @@ use std::ops::Deref;
|
|||
use std::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
|
@ -37,9 +36,7 @@ use vm_device::interrupt::{
|
|||
};
|
||||
use vm_device::{BusDevice, PciBarType, Resource};
|
||||
use vm_memory::{Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, Le32};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
@ -263,7 +260,7 @@ const NOTIFY_OFF_MULTIPLIER: u32 = 4; // A dword per notification address.
|
|||
const VIRTIO_PCI_VENDOR_ID: u16 = 0x1af4;
|
||||
const VIRTIO_PCI_DEVICE_ID_BASE: u16 = 0x1040; // Add to device type to get device ID.
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct QueueState {
|
||||
max_size: u16,
|
||||
size: u16,
|
||||
|
@ -273,7 +270,7 @@ struct QueueState {
|
|||
used_ring: u64,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VirtioPciDeviceState {
|
||||
device_activated: bool,
|
||||
queues: Vec<QueueState>,
|
||||
|
@ -282,8 +279,6 @@ pub struct VirtioPciDeviceState {
|
|||
cap_pci_cfg: Vec<u8>,
|
||||
}
|
||||
|
||||
impl VersionMapped for VirtioPciDeviceState {}
|
||||
|
||||
pub struct VirtioPciDeviceActivator {
|
||||
interrupt: Option<Arc<dyn VirtioInterrupt>>,
|
||||
memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
|
@ -431,15 +426,13 @@ impl VirtioPciDevice {
|
|||
))
|
||||
})?;
|
||||
|
||||
let msix_state =
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), pci::MSIX_CONFIG_ID).map_err(
|
||||
|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
},
|
||||
)?;
|
||||
let msix_state = vm_migration::state_from_id(snapshot.as_ref(), pci::MSIX_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let (msix_config, msix_config_clone) = if msix_num > 0 {
|
||||
let msix_config = Arc::new(Mutex::new(
|
||||
|
@ -473,13 +466,14 @@ impl VirtioPciDevice {
|
|||
};
|
||||
|
||||
let pci_configuration_state =
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), pci::PCI_CONFIGURATION_ID)
|
||||
.map_err(|e| {
|
||||
vm_migration::state_from_id(snapshot.as_ref(), pci::PCI_CONFIGURATION_ID).map_err(
|
||||
|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
},
|
||||
)?;
|
||||
|
||||
let configuration = PciConfiguration::new(
|
||||
VIRTIO_PCI_VENDOR_ID,
|
||||
|
@ -496,13 +490,14 @@ impl VirtioPciDevice {
|
|||
);
|
||||
|
||||
let common_config_state =
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), VIRTIO_PCI_COMMON_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
"Failed to get VirtioPciCommonConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
vm_migration::state_from_id(snapshot.as_ref(), VIRTIO_PCI_COMMON_CONFIG_ID).map_err(
|
||||
|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
"Failed to get VirtioPciCommonConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
},
|
||||
)?;
|
||||
|
||||
let common_config = if let Some(common_config_state) = common_config_state {
|
||||
VirtioPciCommonConfig::new(common_config_state, access_platform)
|
||||
|
@ -523,7 +518,7 @@ impl VirtioPciDevice {
|
|||
|
||||
let state: Option<VirtioPciDeviceState> = snapshot
|
||||
.as_ref()
|
||||
.map(|s| s.to_versioned_state())
|
||||
.map(|s| s.to_state())
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
VirtioPciDeviceError::CreateVirtioPciDevice(anyhow!(
|
||||
|
@ -1289,7 +1284,7 @@ impl Snapshottable for VirtioPciDevice {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
let mut virtio_pci_dev_snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||
let mut virtio_pci_dev_snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
virtio_pci_dev_snapshot
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
VIRTIO_F_IOMMU_PLATFORM,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
io, result,
|
||||
|
@ -18,8 +19,6 @@ use std::{
|
|||
},
|
||||
};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vhost::{
|
||||
vdpa::{VhostVdpa, VhostVdpaIovaRange},
|
||||
vhost_kern::VhostKernFeatures,
|
||||
|
@ -29,9 +28,7 @@ use vhost::{
|
|||
use virtio_queue::{Descriptor, Queue, QueueT};
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
@ -95,7 +92,7 @@ pub enum Error {
|
|||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VdpaState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -107,8 +104,6 @@ pub struct VdpaState {
|
|||
pub backend_features: u64,
|
||||
}
|
||||
|
||||
impl VersionMapped for VdpaState {}
|
||||
|
||||
pub struct Vdpa {
|
||||
common: VirtioCommon,
|
||||
id: String,
|
||||
|
@ -489,7 +484,7 @@ impl Snapshottable for Vdpa {
|
|||
)));
|
||||
}
|
||||
|
||||
let snapshot = Snapshot::new_from_versioned_state(&self.state().map_err(|e| {
|
||||
let snapshot = Snapshot::new_from_state(&self.state().map_err(|e| {
|
||||
MigratableError::Snapshot(anyhow!("Error snapshotting vDPA device: {:?}", e))
|
||||
})?)?;
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ use crate::{GuestMemoryMmap, GuestRegionMmap};
|
|||
use crate::{VirtioInterrupt, VIRTIO_F_IOMMU_PLATFORM};
|
||||
use block::VirtioBlockConfig;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::mem;
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
|
||||
use vhost::vhost_user::message::{
|
||||
VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
|
||||
VHOST_USER_CONFIG_OFFSET,
|
||||
|
@ -32,13 +32,13 @@ use virtio_queue::Queue;
|
|||
use vm_memory::{ByteValued, GuestMemoryAtomic};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
|
||||
Transportable, VersionMapped,
|
||||
Transportable,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const DEFAULT_QUEUE_NUMBER: usize = 1;
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -47,8 +47,6 @@ pub struct State {
|
|||
pub vu_num_queues: usize,
|
||||
}
|
||||
|
||||
impl VersionMapped for State {}
|
||||
|
||||
struct BackendReqHandler {}
|
||||
impl VhostUserFrontendReqHandler for BackendReqHandler {}
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ use crate::{
|
|||
use crate::{GuestMemoryMmap, GuestRegionMmap, MmapRegion};
|
||||
use libc::{c_void, off64_t, pread64, pwrite64};
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, Bytes};
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vhost::vhost_user::message::{
|
||||
VhostUserFSBackendMsg, VhostUserFSBackendMsgFlags, VhostUserProtocolFeatures,
|
||||
VhostUserVirtioFeatures, VHOST_USER_FS_BACKEND_ENTRIES,
|
||||
|
@ -34,14 +34,14 @@ use vm_memory::{
|
|||
};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
|
||||
Transportable, VersionMapped,
|
||||
Transportable,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const NUM_QUEUE_OFFSET: usize = 1;
|
||||
const DEFAULT_QUEUE_NUMBER: usize = 2;
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -51,8 +51,6 @@ pub struct State {
|
|||
pub backend_req_support: bool,
|
||||
}
|
||||
|
||||
impl VersionMapped for State {}
|
||||
|
||||
struct BackendReqHandler {
|
||||
cache_offset: GuestAddress,
|
||||
cache_size: u64,
|
||||
|
@ -272,9 +270,11 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
|
|||
}
|
||||
|
||||
pub const VIRTIO_FS_TAG_LEN: usize = 36;
|
||||
#[derive(Copy, Clone, Versionize)]
|
||||
#[serde_as]
|
||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioFsConfig {
|
||||
#[serde_as(as = "Bytes")]
|
||||
pub tag: [u8; VIRTIO_FS_TAG_LEN],
|
||||
pub num_request_queues: u32,
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ use crate::{
|
|||
VIRTIO_F_RING_INDIRECT_DESC, VIRTIO_F_VERSION_1,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::{atomic::AtomicBool, Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::Versionize;
|
||||
use vhost::vhost_user::message::{
|
||||
VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ use vm_memory::{
|
|||
mmap::MmapRegionError, Address, Error as MmapError, GuestAddressSpace, GuestMemory,
|
||||
GuestMemoryAtomic,
|
||||
};
|
||||
use vm_migration::{protocol::MemoryRangeTable, MigratableError, Snapshot, VersionMapped};
|
||||
use vm_migration::{protocol::MemoryRangeTable, MigratableError, Snapshot};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vu_common_ctrl::VhostUserHandle;
|
||||
|
||||
|
@ -430,11 +430,11 @@ impl VhostUserCommon {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn snapshot<T>(&mut self, state: &T) -> std::result::Result<Snapshot, MigratableError>
|
||||
pub fn snapshot<'a, T>(&mut self, state: &T) -> std::result::Result<Snapshot, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
T: Serialize + Deserialize<'a>,
|
||||
{
|
||||
let snapshot = Snapshot::new_from_versioned_state(state)?;
|
||||
let snapshot = Snapshot::new_from_state(state)?;
|
||||
|
||||
if self.migration_started {
|
||||
self.shutdown();
|
||||
|
|
|
@ -12,12 +12,11 @@ use crate::{
|
|||
use crate::{GuestMemoryMmap, GuestRegionMmap};
|
||||
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler};
|
||||
use virtio_bindings::virtio_net::{
|
||||
|
@ -31,13 +30,13 @@ use virtio_queue::{Queue, QueueT};
|
|||
use vm_memory::{ByteValued, GuestMemoryAtomic};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRangeTable, Migratable, MigratableError, Pausable, Snapshot, Snapshottable,
|
||||
Transportable, VersionMapped,
|
||||
Transportable,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const DEFAULT_QUEUE_NUMBER: usize = 2;
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct State {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
|
@ -46,8 +45,6 @@ pub struct State {
|
|||
pub vu_num_queues: usize,
|
||||
}
|
||||
|
||||
impl VersionMapped for State {}
|
||||
|
||||
struct BackendReqHandler {}
|
||||
impl VhostUserFrontendReqHandler for BackendReqHandler {}
|
||||
|
||||
|
|
|
@ -40,22 +40,19 @@ use crate::{
|
|||
use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Barrier, RwLock};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::Queue;
|
||||
use virtio_queue::QueueOwnedT;
|
||||
use virtio_queue::QueueT;
|
||||
use vm_memory::GuestAddressSpace;
|
||||
use vm_memory::GuestMemoryAtomic;
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
@ -323,14 +320,12 @@ pub struct Vsock<B: VsockBackend> {
|
|||
exit_evt: EventFd,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VsockState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
}
|
||||
|
||||
impl VersionMapped for VsockState {}
|
||||
|
||||
impl<B> Vsock<B>
|
||||
where
|
||||
B: VsockBackend + Sync,
|
||||
|
@ -519,7 +514,7 @@ where
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
impl<B> Transportable for Vsock<B> where B: VsockBackend + Sync + 'static {}
|
||||
|
@ -787,6 +782,7 @@ mod tests {
|
|||
let mut epoll_helper =
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert_eq!(ctx.guest_rxvq.used.idx.get(), 0);
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
|
@ -807,6 +803,7 @@ mod tests {
|
|||
let mut epoll_helper =
|
||||
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
|
||||
|
||||
assert_eq!(ctx.guest_evvq.used.idx.get(), 0);
|
||||
assert!(
|
||||
ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
|
||||
"handle_event() should have failed"
|
||||
|
|
|
@ -256,7 +256,6 @@ mod tests {
|
|||
pub struct TestContext {
|
||||
pub cid: u64,
|
||||
pub mem: GuestMemoryMmap,
|
||||
pub mem_size: usize,
|
||||
pub device: Vsock<TestBackend>,
|
||||
}
|
||||
|
||||
|
@ -267,7 +266,6 @@ mod tests {
|
|||
Self {
|
||||
cid: CID as u64,
|
||||
mem: GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(),
|
||||
mem_size: MEM_SIZE,
|
||||
device: Vsock::new(
|
||||
String::from("vsock"),
|
||||
CID,
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::GuestMemoryMmap;
|
|||
use crate::{VirtioInterrupt, VirtioInterruptType};
|
||||
use anyhow::anyhow;
|
||||
use seccompiler::SeccompAction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
|
@ -24,11 +25,8 @@ use std::sync::atomic::AtomicBool;
|
|||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::time::Instant;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
|
||||
use vm_migration::VersionMapped;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
@ -197,15 +195,13 @@ pub struct Watchdog {
|
|||
exit_evt: EventFd,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct WatchdogState {
|
||||
pub avail_features: u64,
|
||||
pub acked_features: u64,
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
impl VersionMapped for WatchdogState {}
|
||||
|
||||
impl Watchdog {
|
||||
/// Create a new virtio watchdog device that will reboot VM if the guest hangs
|
||||
pub fn new(
|
||||
|
@ -420,7 +416,7 @@ impl Snapshottable for Watchdog {
|
|||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
Snapshot::new_from_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,10 +219,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn new_fails_overflow() {
|
||||
assert_eq!(
|
||||
AddressAllocator::new(GuestAddress(u64::max_value()), 0x100),
|
||||
None
|
||||
);
|
||||
assert_eq!(AddressAllocator::new(GuestAddress(u64::MAX), 0x100), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -12,7 +12,7 @@ mshv = ["vfio-ioctls/mshv"]
|
|||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap"] }
|
||||
|
|
|
@ -6,9 +6,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.115"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }
|
||||
|
|
|
@ -7,21 +7,9 @@ use crate::protocol::MemoryRangeTable;
|
|||
use anyhow::anyhow;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize};
|
||||
|
||||
pub mod protocol;
|
||||
|
||||
/// Global VMM version for versioning
|
||||
const MAJOR_VERSION: u16 = 38;
|
||||
const MINOR_VERSION: u16 = 0;
|
||||
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;
|
||||
|
||||
pub trait VersionMapped {
|
||||
fn version_map() -> VersionMap {
|
||||
VersionMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MigratableError {
|
||||
#[error("Failed to pause migratable component: {0}")]
|
||||
|
@ -80,7 +68,9 @@ pub trait Pausable {
|
|||
/// Splitting a component migration data into different sections
|
||||
/// allows for easier and forward compatible extensions.
|
||||
#[derive(Clone, Default, Deserialize, Serialize)]
|
||||
pub struct SnapshotData(pub Vec<u8>);
|
||||
pub struct SnapshotData {
|
||||
state: String,
|
||||
}
|
||||
|
||||
impl SnapshotData {
|
||||
/// Generate the state data from the snapshot data
|
||||
|
@ -88,16 +78,7 @@ impl SnapshotData {
|
|||
where
|
||||
T: Deserialize<'a>,
|
||||
{
|
||||
serde_json::from_slice(&self.0)
|
||||
.map_err(|e| MigratableError::Restore(anyhow!("Error deserialising: {}", e)))
|
||||
}
|
||||
|
||||
/// Generate versioned state
|
||||
pub fn to_versioned_state<T>(&self) -> Result<T, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
T::deserialize(&mut self.0.as_slice(), &T::version_map(), VMM_VERSION)
|
||||
serde_json::from_str(&self.state)
|
||||
.map_err(|e| MigratableError::Restore(anyhow!("Error deserialising: {}", e)))
|
||||
}
|
||||
|
||||
|
@ -106,23 +87,10 @@ impl SnapshotData {
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let data = serde_json::to_vec(state)
|
||||
let state = serde_json::to_string(state)
|
||||
.map_err(|e| MigratableError::Snapshot(anyhow!("Error serialising: {}", e)))?;
|
||||
|
||||
Ok(SnapshotData(data))
|
||||
}
|
||||
|
||||
/// Create from versioned state
|
||||
pub fn new_from_versioned_state<T>(state: &T) -> Result<Self, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
let mut data = Vec::new();
|
||||
state
|
||||
.serialize(&mut data, &T::version_map(), VMM_VERSION)
|
||||
.map_err(|e| MigratableError::Snapshot(anyhow!("Error serialising: {}", e)))?;
|
||||
|
||||
Ok(SnapshotData(data))
|
||||
Ok(SnapshotData { state })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,16 +131,6 @@ impl Snapshot {
|
|||
Ok(Snapshot::from_data(SnapshotData::new_from_state(state)?))
|
||||
}
|
||||
|
||||
/// Create from versioned state
|
||||
pub fn new_from_versioned_state<T>(state: &T) -> Result<Self, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
Ok(Snapshot::from_data(SnapshotData::new_from_versioned_state(
|
||||
state,
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Add a sub-component's Snapshot to the Snapshot.
|
||||
pub fn add_snapshot(&mut self, id: String, snapshot: Snapshot) {
|
||||
self.snapshots.insert(id, snapshot);
|
||||
|
@ -188,34 +146,21 @@ impl Snapshot {
|
|||
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing snapshot data")))?
|
||||
.to_state()
|
||||
}
|
||||
|
||||
/// Generate versioned state
|
||||
pub fn to_versioned_state<T>(&self) -> Result<T, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
self.snapshot_data
|
||||
.as_ref()
|
||||
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing snapshot data")))?
|
||||
.to_versioned_state()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot_from_id(snapshot: Option<&Snapshot>, id: &str) -> Option<Snapshot> {
|
||||
snapshot.and_then(|s| s.snapshots.get(id).cloned())
|
||||
}
|
||||
|
||||
pub fn versioned_state_from_id<T>(
|
||||
snapshot: Option<&Snapshot>,
|
||||
id: &str,
|
||||
) -> Result<Option<T>, MigratableError>
|
||||
pub fn state_from_id<'a, T>(s: Option<&'a Snapshot>, id: &str) -> Result<Option<T>, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
T: Deserialize<'a>,
|
||||
{
|
||||
snapshot
|
||||
.and_then(|s| s.snapshots.get(id).cloned())
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
if let Some(s) = s.as_ref() {
|
||||
s.snapshots.get(id).map(|s| s.to_state()).transpose()
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshottable component can be snapshotted.
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use crate::{MigratableError, VersionMapped};
|
||||
use crate::MigratableError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::{Read, Write};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_memory::ByteValued;
|
||||
|
||||
// Migration protocol
|
||||
|
@ -199,19 +197,17 @@ impl Response {
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
pub struct MemoryRange {
|
||||
pub gpa: u64,
|
||||
pub length: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
pub struct MemoryRangeTable {
|
||||
data: Vec<MemoryRange>,
|
||||
}
|
||||
|
||||
impl VersionMapped for MemoryRangeTable {}
|
||||
|
||||
impl MemoryRangeTable {
|
||||
pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self {
|
||||
let mut table = MemoryRangeTable::default();
|
||||
|
|
|
@ -9,5 +9,5 @@ default = []
|
|||
|
||||
[dependencies]
|
||||
log = "0.4.21"
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
|
|
@ -7,12 +7,13 @@ edition = "2021"
|
|||
[features]
|
||||
default = []
|
||||
dbus_api = ["blocking", "futures", "zbus"]
|
||||
dhat-heap = ["dhat"] # For heap profiling
|
||||
guest_debug = ["kvm", "gdbstub", "gdbstub_arch"]
|
||||
igvm = ["hex", "igvm_parser", "igvm_defs", "mshv-bindings", "range_map_vec"]
|
||||
igvm = ["hex", "dep:igvm", "igvm_defs", "mshv-bindings", "range_map_vec"]
|
||||
io_uring = ["block/io_uring"]
|
||||
kvm = ["hypervisor/kvm", "vfio-ioctls/kvm", "vm-device/kvm", "pci/kvm"]
|
||||
mshv = ["hypervisor/mshv", "vfio-ioctls/mshv", "vm-device/mshv", "pci/mshv"]
|
||||
sev_snp = ["arch/sev_snp", "hypervisor/sev_snp"]
|
||||
sev_snp = ["arch/sev_snp", "hypervisor/sev_snp", "virtio-devices/sev_snp"]
|
||||
tdx = ["arch/tdx", "hypervisor/tdx"]
|
||||
tracing = ["tracer/tracing"]
|
||||
|
||||
|
@ -27,6 +28,7 @@ blocking = { version = "1.5.1", optional = true }
|
|||
cfg-if = "1.0.0"
|
||||
clap = "4.5.4"
|
||||
devices = { path = "../devices" }
|
||||
dhat = { version = "0.3.3", optional = true }
|
||||
epoll = "4.3.3"
|
||||
event_monitor = { path = "../event_monitor" }
|
||||
flume = "0.11.0"
|
||||
|
@ -35,8 +37,8 @@ gdbstub = { version = "0.7.1", optional = true }
|
|||
gdbstub_arch = { version = "0.3.0", optional = true }
|
||||
hex = { version = "0.4.3", optional = true }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
|
||||
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
|
||||
igvm = { version = "0.2.0", optional = true }
|
||||
igvm_defs = { version = "0.2.0", optional = true }
|
||||
libc = "0.2.153"
|
||||
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
|
||||
log = "0.4.21"
|
||||
|
@ -53,15 +55,13 @@ serde = { version = "1.0.197", features = ["rc", "derive"] }
|
|||
serde_json = "1.0.115"
|
||||
serial_buffer = { path = "../serial_buffer" }
|
||||
signal-hook = "0.3.17"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.60"
|
||||
tracer = { path = "../tracer" }
|
||||
uuid = "1.8.0"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
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" }
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright © 2024 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rustc-check-cfg=cfg(fuzzing)");
|
||||
}
|
|
@ -618,6 +618,10 @@ components:
|
|||
pvpanic:
|
||||
type: boolean
|
||||
default: false
|
||||
pci_segments:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/PciSegmentConfig"
|
||||
platform:
|
||||
$ref: "#/components/schemas/PlatformConfig"
|
||||
tpm:
|
||||
|
@ -663,11 +667,9 @@ components:
|
|||
properties:
|
||||
boot_vcpus:
|
||||
minimum: 1
|
||||
default: 1
|
||||
type: integer
|
||||
max_vcpus:
|
||||
minimum: 1
|
||||
default: 1
|
||||
type: integer
|
||||
topology:
|
||||
$ref: "#/components/schemas/CpuTopology"
|
||||
|
@ -683,6 +685,21 @@ components:
|
|||
features:
|
||||
$ref: "#/components/schemas/CpuFeatures"
|
||||
|
||||
PciSegmentConfig:
|
||||
required:
|
||||
- pci_segment
|
||||
type: object
|
||||
properties:
|
||||
pci_segment:
|
||||
type: integer
|
||||
format: int16
|
||||
mmio32_aperture_weight:
|
||||
type: integer
|
||||
format: int32
|
||||
mmio64_aperture_weight:
|
||||
type: integer
|
||||
format: int32
|
||||
|
||||
PlatformConfig:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -717,7 +734,6 @@ components:
|
|||
size:
|
||||
type: integer
|
||||
format: int64
|
||||
default: 512 MB
|
||||
file:
|
||||
type: string
|
||||
mergeable:
|
||||
|
@ -753,7 +769,6 @@ components:
|
|||
size:
|
||||
type: integer
|
||||
format: int64
|
||||
default: 512 MB
|
||||
hotplug_size:
|
||||
type: integer
|
||||
format: int64
|
||||
|
@ -838,7 +853,7 @@ components:
|
|||
type: string
|
||||
rate_limiter_config:
|
||||
$ref: "#/components/schemas/RateLimiterConfig"
|
||||
|
||||
|
||||
VirtQueueAffinity:
|
||||
required:
|
||||
- queue_index
|
||||
|
@ -944,7 +959,6 @@ components:
|
|||
properties:
|
||||
src:
|
||||
type: string
|
||||
default: "/dev/urandom"
|
||||
iommu:
|
||||
type: boolean
|
||||
default: false
|
||||
|
|
|
@ -98,6 +98,8 @@ pub enum Error {
|
|||
ParseUserDevice(OptionParserError),
|
||||
/// Missing socket for userspace device
|
||||
ParseUserDeviceSocketMissing,
|
||||
/// Error parsing pci segment options
|
||||
ParsePciSegment(OptionParserError),
|
||||
/// Failed parsing platform parameters
|
||||
ParsePlatform(OptionParserError),
|
||||
/// Failed parsing vDPA device
|
||||
|
@ -170,6 +172,8 @@ pub enum ValidationError {
|
|||
InvalidNumPciSegments(u16),
|
||||
/// Invalid PCI segment id
|
||||
InvalidPciSegment(u16),
|
||||
/// Invalid PCI segment aperture weight
|
||||
InvalidPciSegmentApertureWeight(u32),
|
||||
/// Balloon too big
|
||||
BalloonLargerThanRam(u64, u64),
|
||||
/// On a IOMMU segment but not behind IOMMU
|
||||
|
@ -279,6 +283,9 @@ impl fmt::Display for ValidationError {
|
|||
InvalidPciSegment(pci_segment) => {
|
||||
write!(f, "Invalid PCI segment id: {pci_segment}")
|
||||
}
|
||||
InvalidPciSegmentApertureWeight(aperture_weight) => {
|
||||
write!(f, "Invalid PCI segment aperture weight: {aperture_weight}")
|
||||
}
|
||||
BalloonLargerThanRam(balloon_size, ram_size) => {
|
||||
write!(
|
||||
f,
|
||||
|
@ -395,6 +402,7 @@ impl fmt::Display for Error {
|
|||
ParseTdx(o) => write!(f, "Error parsing --tdx: {o}"),
|
||||
#[cfg(feature = "tdx")]
|
||||
FirmwarePathMissing => write!(f, "TDX firmware missing"),
|
||||
ParsePciSegment(o) => write!(f, "Error parsing --pci-segment: {o}"),
|
||||
ParsePlatform(o) => write!(f, "Error parsing --platform: {o}"),
|
||||
ParseVdpa(o) => write!(f, "Error parsing --vdpa: {o}"),
|
||||
ParseVdpaPathMissing => write!(f, "Error parsing --vdpa: path missing"),
|
||||
|
@ -444,6 +452,7 @@ pub struct VmParams<'a> {
|
|||
pub watchdog: bool,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
pub gdb: bool,
|
||||
pub pci_segments: Option<Vec<&'a str>>,
|
||||
pub platform: Option<&'a str>,
|
||||
pub tpm: Option<&'a str>,
|
||||
#[cfg(feature = "igvm")]
|
||||
|
@ -504,6 +513,9 @@ impl<'a> VmParams<'a> {
|
|||
.get_many::<String>("numa")
|
||||
.map(|x| x.map(|y| y as &str).collect());
|
||||
let watchdog = args.get_flag("watchdog");
|
||||
let pci_segments: Option<Vec<&str>> = args
|
||||
.get_many::<String>("pci-segment")
|
||||
.map(|x| x.map(|y| y as &str).collect());
|
||||
let platform = args.get_one::<String>("platform").map(|x| x as &str);
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let gdb = args.contains_id("gdb");
|
||||
|
@ -542,6 +554,7 @@ impl<'a> VmParams<'a> {
|
|||
watchdog,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb,
|
||||
pci_segments,
|
||||
platform,
|
||||
tpm,
|
||||
#[cfg(feature = "igvm")]
|
||||
|
@ -678,6 +691,64 @@ impl CpusConfig {
|
|||
}
|
||||
}
|
||||
|
||||
impl PciSegmentConfig {
|
||||
pub const SYNTAX: &'static str = "PCI Segment parameters \
|
||||
\"pci_segment=<segment_id>,mmio32_aperture_weight=<scale>,mmio64_aperture_weight=<scale>\"";
|
||||
|
||||
pub fn parse(disk: &str) -> Result<Self> {
|
||||
let mut parser = OptionParser::new();
|
||||
parser
|
||||
.add("mmio32_aperture_weight")
|
||||
.add("mmio64_aperture_weight")
|
||||
.add("pci_segment");
|
||||
parser.parse(disk).map_err(Error::ParsePciSegment)?;
|
||||
|
||||
let pci_segment = parser
|
||||
.convert("pci_segment")
|
||||
.map_err(Error::ParsePciSegment)?
|
||||
.unwrap_or_default();
|
||||
let mmio32_aperture_weight = parser
|
||||
.convert("mmio32_aperture_weight")
|
||||
.map_err(Error::ParsePciSegment)?
|
||||
.unwrap_or(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT);
|
||||
let mmio64_aperture_weight = parser
|
||||
.convert("mmio64_aperture_weight")
|
||||
.map_err(Error::ParsePciSegment)?
|
||||
.unwrap_or(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT);
|
||||
|
||||
Ok(PciSegmentConfig {
|
||||
pci_segment,
|
||||
mmio32_aperture_weight,
|
||||
mmio64_aperture_weight,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> {
|
||||
let num_pci_segments = match &vm_config.platform {
|
||||
Some(platform_config) => platform_config.num_pci_segments,
|
||||
None => 1,
|
||||
};
|
||||
|
||||
if self.pci_segment >= num_pci_segments {
|
||||
return Err(ValidationError::InvalidPciSegment(self.pci_segment));
|
||||
}
|
||||
|
||||
if self.mmio32_aperture_weight == 0 {
|
||||
return Err(ValidationError::InvalidPciSegmentApertureWeight(
|
||||
self.mmio32_aperture_weight,
|
||||
));
|
||||
}
|
||||
|
||||
if self.mmio64_aperture_weight == 0 {
|
||||
return Err(ValidationError::InvalidPciSegmentApertureWeight(
|
||||
self.mmio64_aperture_weight,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformConfig {
|
||||
pub fn parse(platform: &str) -> Result<Self> {
|
||||
let mut parser = OptionParser::new();
|
||||
|
@ -2449,6 +2520,12 @@ impl VmConfig {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(pci_segments) = &self.pci_segments {
|
||||
for pci_segment in pci_segments {
|
||||
pci_segment.validate(self)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.platform.as_ref().map(|p| p.validate()).transpose()?;
|
||||
self.iommu |= self
|
||||
.platform
|
||||
|
@ -2557,6 +2634,16 @@ impl VmConfig {
|
|||
vsock = Some(vsock_config);
|
||||
}
|
||||
|
||||
let mut pci_segments: Option<Vec<PciSegmentConfig>> = None;
|
||||
if let Some(pci_segment_list) = &vm_params.pci_segments {
|
||||
let mut pci_segment_config_list = Vec::new();
|
||||
for item in pci_segment_list.iter() {
|
||||
let pci_segment_config = PciSegmentConfig::parse(item)?;
|
||||
pci_segment_config_list.push(pci_segment_config);
|
||||
}
|
||||
pci_segments = Some(pci_segment_config_list);
|
||||
}
|
||||
|
||||
let platform = vm_params.platform.map(PlatformConfig::parse).transpose()?;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -2643,6 +2730,7 @@ impl VmConfig {
|
|||
watchdog: vm_params.watchdog,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb,
|
||||
pci_segments,
|
||||
platform,
|
||||
tpm,
|
||||
preserved_fds: None,
|
||||
|
@ -2764,6 +2852,7 @@ impl Clone for VmConfig {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
sgx_epc: self.sgx_epc.clone(),
|
||||
numa: self.numa.clone(),
|
||||
pci_segments: self.pci_segments.clone(),
|
||||
platform: self.platform.clone(),
|
||||
tpm: self.tpm.clone(),
|
||||
preserved_fds: self
|
||||
|
@ -2960,6 +3049,46 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pci_segment_parsing() -> Result<()> {
|
||||
assert_eq!(
|
||||
PciSegmentConfig::parse("pci_segment=0")?,
|
||||
PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 1,
|
||||
mmio64_aperture_weight: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
PciSegmentConfig::parse(
|
||||
"pci_segment=0,mmio32_aperture_weight=1,mmio64_aperture_weight=1"
|
||||
)?,
|
||||
PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 1,
|
||||
mmio64_aperture_weight: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
PciSegmentConfig::parse("pci_segment=0,mmio32_aperture_weight=2")?,
|
||||
PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 2,
|
||||
mmio64_aperture_weight: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
PciSegmentConfig::parse("pci_segment=0,mmio64_aperture_weight=2")?,
|
||||
PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 1,
|
||||
mmio64_aperture_weight: 2,
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn disk_fixture() -> DiskConfig {
|
||||
DiskConfig {
|
||||
path: Some(PathBuf::from("/path/to_file")),
|
||||
|
@ -3536,6 +3665,7 @@ mod tests {
|
|||
watchdog: false,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb: false,
|
||||
pci_segments: None,
|
||||
platform: None,
|
||||
tpm: None,
|
||||
preserved_fds: None,
|
||||
|
@ -3946,6 +4076,28 @@ mod tests {
|
|||
Err(ValidationError::PciSegmentReused(1, 0, 1))
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.pci_segments = Some(vec![PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 1,
|
||||
mmio64_aperture_weight: 0,
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::InvalidPciSegmentApertureWeight(0))
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.pci_segments = Some(vec![PciSegmentConfig {
|
||||
pci_segment: 0,
|
||||
mmio32_aperture_weight: 0,
|
||||
mmio64_aperture_weight: 1,
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::InvalidPciSegmentApertureWeight(0))
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.numa = Some(vec![
|
||||
NumaConfig {
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
use crate::sigwinch_listener::listen_for_sigwinch_on_tty;
|
||||
use crate::vm_config::ConsoleOutputMode;
|
||||
use crate::Vmm;
|
||||
use libc::cfmakeraw;
|
||||
use libc::isatty;
|
||||
use libc::tcgetattr;
|
||||
use libc::tcsetattr;
|
||||
use libc::termios;
|
||||
use libc::TCSANOW;
|
||||
use std::fs::read_link;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io;
|
||||
use std::io::stdout;
|
||||
use std::mem::zeroed;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::fd::IntoRawFd;
|
||||
use std::os::fd::RawFd;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Errors associated with console devices
|
||||
#[derive(Debug)]
|
||||
pub enum ConsoleDeviceError {
|
||||
/// Error creating console device
|
||||
CreateConsoleDevice(io::Error),
|
||||
|
||||
/// Error setting pty raw mode
|
||||
SetPtyRaw(vmm_sys_util::errno::Error),
|
||||
|
||||
/// Cannot duplicate file descriptor
|
||||
DupFd(vmm_sys_util::errno::Error),
|
||||
|
||||
/// Error starting sigwinch listener
|
||||
StartSigwinchListener(std::io::Error),
|
||||
}
|
||||
|
||||
pub type ConsoleDeviceResult<T> = result::Result<T, ConsoleDeviceError>;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ConsoleInfo {
|
||||
// For each of File, Pty, Tty, Socket modes, xxxx_main_fd will hold the FD
|
||||
// of the opened path.
|
||||
pub console_main_fd: Option<RawFd>,
|
||||
|
||||
pub serial_main_fd: Option<RawFd>,
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub debug_main_fd: Option<RawFd>,
|
||||
}
|
||||
|
||||
fn modify_mode<F: FnOnce(&mut termios)>(
|
||||
fd: RawFd,
|
||||
f: F,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
) -> vmm_sys_util::errno::Result<()> {
|
||||
// SAFETY: safe because we check the return value of isatty.
|
||||
if unsafe { isatty(fd) } != 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// SAFETY: The following pair are safe because termios gets totally overwritten by tcgetattr
|
||||
// and we check the return result.
|
||||
let mut termios: termios = unsafe { zeroed() };
|
||||
// SAFETY: see above
|
||||
let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) };
|
||||
if ret < 0 {
|
||||
return vmm_sys_util::errno::errno_result();
|
||||
}
|
||||
let mut original_termios_opt = original_termios_opt.lock().unwrap();
|
||||
if original_termios_opt.is_none() {
|
||||
original_termios_opt.replace(termios);
|
||||
}
|
||||
|
||||
f(&mut termios);
|
||||
// SAFETY: Safe because the syscall will only read the extent of termios and we check
|
||||
// the return result.
|
||||
let ret = unsafe { tcsetattr(fd, TCSANOW, &termios as *const _) };
|
||||
if ret < 0 {
|
||||
return vmm_sys_util::errno::errno_result();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_raw_mode(
|
||||
f: &dyn AsRawFd,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
) -> ConsoleDeviceResult<()> {
|
||||
// SAFETY: FFI call. Variable t is guaranteed to be a valid termios from modify_mode.
|
||||
modify_mode(
|
||||
f.as_raw_fd(),
|
||||
|t| unsafe { cfmakeraw(t) },
|
||||
original_termios_opt,
|
||||
)
|
||||
.map_err(ConsoleDeviceError::SetPtyRaw)
|
||||
}
|
||||
|
||||
const TIOCSPTLCK: libc::c_int = 0x4004_5431;
|
||||
const TIOCGTPEER: libc::c_int = 0x5441;
|
||||
|
||||
pub fn create_pty() -> io::Result<(File, File, PathBuf)> {
|
||||
// Try to use /dev/pts/ptmx first then fall back to /dev/ptmx
|
||||
// This is done to try and use the devpts filesystem that
|
||||
// could be available for use in the process's namespace first.
|
||||
// Ideally these are all the same file though but different
|
||||
// kernels could have things setup differently.
|
||||
// See https://www.kernel.org/doc/Documentation/filesystems/devpts.txt
|
||||
// for further details.
|
||||
|
||||
let custom_flags = libc::O_NONBLOCK;
|
||||
let main = match OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.custom_flags(custom_flags)
|
||||
.open("/dev/pts/ptmx")
|
||||
{
|
||||
Ok(f) => f,
|
||||
_ => OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.custom_flags(custom_flags)
|
||||
.open("/dev/ptmx")?,
|
||||
};
|
||||
let mut unlock: libc::c_ulong = 0;
|
||||
// SAFETY: FFI call into libc, trivially safe
|
||||
unsafe { libc::ioctl(main.as_raw_fd(), TIOCSPTLCK as _, &mut unlock) };
|
||||
|
||||
// SAFETY: FFI call into libc, trivially safe
|
||||
let sub_fd = unsafe {
|
||||
libc::ioctl(
|
||||
main.as_raw_fd(),
|
||||
TIOCGTPEER as _,
|
||||
libc::O_NOCTTY | libc::O_RDWR,
|
||||
)
|
||||
};
|
||||
if sub_fd == -1 {
|
||||
return vmm_sys_util::errno::errno_result().map_err(|e| e.into());
|
||||
}
|
||||
|
||||
let proc_path = PathBuf::from(format!("/proc/self/fd/{sub_fd}"));
|
||||
let path = read_link(proc_path)?;
|
||||
|
||||
// SAFETY: sub_fd is checked to be valid before being wrapped in File
|
||||
Ok((main, unsafe { File::from_raw_fd(sub_fd) }, path))
|
||||
}
|
||||
|
||||
pub fn pre_create_console_devices(vmm: &mut Vmm) -> ConsoleDeviceResult<ConsoleInfo> {
|
||||
let vm_config = vmm.vm_config.as_mut().unwrap().clone();
|
||||
let mut vmconfig = vm_config.lock().unwrap();
|
||||
let mut console_info = ConsoleInfo::default();
|
||||
|
||||
match vmconfig.console.mode {
|
||||
ConsoleOutputMode::File => {
|
||||
let file = File::create(vmconfig.console.file.as_ref().unwrap())
|
||||
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.console_main_fd = Some(file.into_raw_fd());
|
||||
}
|
||||
ConsoleOutputMode::Pty => {
|
||||
let (main_fd, sub_fd, path) =
|
||||
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.console_main_fd = Some(main_fd.into_raw_fd());
|
||||
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
|
||||
vmconfig.console.file = Some(path.clone());
|
||||
vmm.console_resize_pipe = Some(
|
||||
listen_for_sigwinch_on_tty(
|
||||
sub_fd,
|
||||
&vmm.seccomp_action,
|
||||
vmm.hypervisor.hypervisor_type(),
|
||||
)
|
||||
.map_err(ConsoleDeviceError::StartSigwinchListener)?,
|
||||
);
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
// Duplicating the file descriptors like this is needed as otherwise
|
||||
// they will be closed on a reboot and the numbers reused
|
||||
|
||||
// SAFETY: FFI call to dup. Trivially safe.
|
||||
let stdout = unsafe { libc::dup(libc::STDOUT_FILENO) };
|
||||
if stdout == -1 {
|
||||
return vmm_sys_util::errno::errno_result().map_err(ConsoleDeviceError::DupFd);
|
||||
}
|
||||
// SAFETY: stdout is valid and owned solely by us.
|
||||
let stdout = unsafe { File::from_raw_fd(stdout) };
|
||||
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
if unsafe { libc::isatty(libc::STDOUT_FILENO) } == 1 {
|
||||
vmm.console_resize_pipe = Some(
|
||||
listen_for_sigwinch_on_tty(
|
||||
stdout.try_clone().unwrap(),
|
||||
&vmm.seccomp_action,
|
||||
vmm.hypervisor.hypervisor_type(),
|
||||
)
|
||||
.map_err(ConsoleDeviceError::StartSigwinchListener)?,
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure stdout is in raw mode, if it's a terminal.
|
||||
set_raw_mode(&stdout, vmm.original_termios_opt.clone())?;
|
||||
console_info.console_main_fd = Some(stdout.into_raw_fd());
|
||||
}
|
||||
ConsoleOutputMode::Null | ConsoleOutputMode::Socket | ConsoleOutputMode::Off => {}
|
||||
}
|
||||
|
||||
match vmconfig.serial.mode {
|
||||
ConsoleOutputMode::File => {
|
||||
let file = File::create(vmconfig.serial.file.as_ref().unwrap())
|
||||
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.serial_main_fd = Some(file.into_raw_fd());
|
||||
}
|
||||
ConsoleOutputMode::Pty => {
|
||||
let (main_fd, sub_fd, path) =
|
||||
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.serial_main_fd = Some(main_fd.into_raw_fd());
|
||||
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
|
||||
vmconfig.serial.file = Some(path.clone());
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
let out = stdout();
|
||||
console_info.serial_main_fd = Some(out.as_raw_fd());
|
||||
set_raw_mode(&out, vmm.original_termios_opt.clone())?;
|
||||
}
|
||||
ConsoleOutputMode::Socket => {
|
||||
let listener = UnixListener::bind(vmconfig.serial.socket.as_ref().unwrap())
|
||||
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.serial_main_fd = Some(listener.into_raw_fd());
|
||||
}
|
||||
ConsoleOutputMode::Null | ConsoleOutputMode::Off => {}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
match vmconfig.debug_console.mode {
|
||||
ConsoleOutputMode::File => {
|
||||
let file = File::create(vmconfig.debug_console.file.as_ref().unwrap())
|
||||
.map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.debug_main_fd = Some(file.into_raw_fd());
|
||||
}
|
||||
ConsoleOutputMode::Pty => {
|
||||
let (main_fd, sub_fd, path) =
|
||||
create_pty().map_err(ConsoleDeviceError::CreateConsoleDevice)?;
|
||||
console_info.debug_main_fd = Some(main_fd.into_raw_fd());
|
||||
set_raw_mode(&sub_fd.as_raw_fd(), vmm.original_termios_opt.clone())?;
|
||||
vmconfig.debug_console.file = Some(path.clone());
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
let out = stdout();
|
||||
console_info.debug_main_fd = Some(out.as_raw_fd());
|
||||
set_raw_mode(&out, vmm.original_termios_opt.clone())?;
|
||||
}
|
||||
ConsoleOutputMode::Null | ConsoleOutputMode::Socket | ConsoleOutputMode::Off => {}
|
||||
}
|
||||
|
||||
Ok(console_info)
|
||||
}
|
|
@ -1147,15 +1147,6 @@ impl CpuManager {
|
|||
unreachable!("Couldn't get a mutable reference from Arc<dyn Vcpu> as there are multiple instances");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!(
|
||||
"VCPU generated error: {:?}",
|
||||
Error::UnexpectedVmExit
|
||||
);
|
||||
vcpu_run_interrupted.store(true, Ordering::SeqCst);
|
||||
exit_evt.write(1).unwrap();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
Err(e) => {
|
||||
|
|
|
@ -13,15 +13,16 @@ use crate::config::{
|
|||
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig,
|
||||
VdpaConfig, VhostMode, VmConfig, VsockConfig,
|
||||
};
|
||||
use crate::console_devices::ConsoleDeviceError;
|
||||
use crate::console_devices::ConsoleInfo;
|
||||
use crate::cpu::{CpuManager, CPU_MANAGER_ACPI_SIZE};
|
||||
use crate::device_tree::{DeviceNode, DeviceTree};
|
||||
use crate::interrupt::LegacyUserspaceInterruptManager;
|
||||
use crate::interrupt::MsiInterruptManager;
|
||||
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager, MEMORY_MANAGER_ACPI_SIZE};
|
||||
use crate::pci_segment::PciSegment;
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::serial_manager::{Error as SerialManagerError, SerialManager};
|
||||
use crate::sigwinch_listener::start_sigwinch_listener;
|
||||
use crate::vm_config::DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT;
|
||||
use crate::GuestRegionMmap;
|
||||
use crate::PciDeviceInfo;
|
||||
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
||||
|
@ -52,10 +53,10 @@ use devices::legacy::Pl011;
|
|||
use devices::{
|
||||
interrupt_controller, interrupt_controller::InterruptController, AcpiNotificationFlags,
|
||||
};
|
||||
use hypervisor::{HypervisorType, IoEventAddress};
|
||||
use hypervisor::IoEventAddress;
|
||||
use libc::{
|
||||
cfmakeraw, isatty, tcgetattr, tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED,
|
||||
O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW,
|
||||
tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE,
|
||||
TCSANOW,
|
||||
};
|
||||
use pci::{
|
||||
DeviceRelocation, MmioRegion, PciBarRegionType, PciBdf, PciDevice, VfioDmaMapping,
|
||||
|
@ -67,10 +68,10 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::fs::{read_link, File, OpenOptions};
|
||||
use std::io::{self, stdout, Seek, SeekFrom};
|
||||
use std::mem::zeroed;
|
||||
use std::num::Wrapping;
|
||||
use std::os::fd::RawFd;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -96,8 +97,8 @@ use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion};
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
use vm_memory::{GuestAddressSpace, GuestMemory};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRangeTable, snapshot_from_id, versioned_state_from_id, Migratable,
|
||||
MigratableError, Pausable, Snapshot, SnapshotData, Snapshottable, Transportable,
|
||||
protocol::MemoryRangeTable, snapshot_from_id, state_from_id, Migratable, MigratableError,
|
||||
Pausable, Snapshot, SnapshotData, Snapshottable, Transportable,
|
||||
};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vm_virtio::VirtioDeviceType;
|
||||
|
@ -269,7 +270,7 @@ pub enum DeviceManagerError {
|
|||
DebugconPtyOpen(io::Error),
|
||||
|
||||
/// Error setting pty raw mode
|
||||
SetPtyRaw(vmm_sys_util::errno::Error),
|
||||
SetPtyRaw(ConsoleDeviceError),
|
||||
|
||||
/// Error getting pty peer
|
||||
GetPtyPeer(vmm_sys_util::errno::Error),
|
||||
|
@ -493,6 +494,15 @@ pub enum DeviceManagerError {
|
|||
|
||||
/// Cannot create a RateLimiterGroup
|
||||
RateLimiterGroupCreate(rate_limiter::group::Error),
|
||||
|
||||
/// Cannot start sigwinch listener
|
||||
StartSigwinchListener(std::io::Error),
|
||||
|
||||
// Invalid console info
|
||||
InvalidConsoleInfo,
|
||||
|
||||
// Invalid console fd
|
||||
InvalidConsoleFd,
|
||||
}
|
||||
|
||||
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
||||
|
@ -814,24 +824,12 @@ pub struct AcpiPlatformAddresses {
|
|||
}
|
||||
|
||||
pub struct DeviceManager {
|
||||
// The underlying hypervisor
|
||||
hypervisor_type: HypervisorType,
|
||||
|
||||
// Manage address space related to devices
|
||||
address_manager: Arc<AddressManager>,
|
||||
|
||||
// Console abstraction
|
||||
console: Arc<Console>,
|
||||
|
||||
// console PTY
|
||||
console_pty: Option<Arc<Mutex<PtyPair>>>,
|
||||
|
||||
// serial PTY
|
||||
serial_pty: Option<Arc<Mutex<PtyPair>>>,
|
||||
|
||||
// debug-console PTY
|
||||
debug_console_pty: Option<Arc<Mutex<PtyPair>>>,
|
||||
|
||||
// Serial Manager
|
||||
serial_manager: Option<Arc<SerialManager>>,
|
||||
|
||||
|
@ -969,12 +967,39 @@ pub struct DeviceManager {
|
|||
mmio_regions: Arc<Mutex<Vec<MmioRegion>>>,
|
||||
}
|
||||
|
||||
fn create_mmio_allocators(
|
||||
start: u64,
|
||||
end: u64,
|
||||
num_pci_segments: u16,
|
||||
weights: Vec<u32>,
|
||||
alignment: u64,
|
||||
) -> Vec<Arc<Mutex<AddressAllocator>>> {
|
||||
let total_weight: u32 = weights.iter().sum();
|
||||
|
||||
// Start each PCI segment mmio range on an aligned boundary
|
||||
let pci_segment_mmio_size = (end - start + 1) / (alignment * total_weight as u64) * alignment;
|
||||
|
||||
let mut mmio_allocators = vec![];
|
||||
let mut i = 0;
|
||||
for segment_id in 0..num_pci_segments as u64 {
|
||||
let weight = weights[segment_id as usize] as u64;
|
||||
let mmio_start = start + i * pci_segment_mmio_size;
|
||||
let mmio_size = pci_segment_mmio_size * weight;
|
||||
let allocator = Arc::new(Mutex::new(
|
||||
AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(),
|
||||
));
|
||||
mmio_allocators.push(allocator);
|
||||
i += weight;
|
||||
}
|
||||
|
||||
mmio_allocators
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
#[cfg(target_arch = "x86_64")] io_bus: Arc<Bus>,
|
||||
mmio_bus: Arc<Bus>,
|
||||
hypervisor_type: HypervisorType,
|
||||
vm: Arc<dyn hypervisor::Vm>,
|
||||
config: Arc<Mutex<VmConfig>>,
|
||||
memory_manager: Arc<Mutex<MemoryManager>>,
|
||||
|
@ -1009,22 +1034,16 @@ impl DeviceManager {
|
|||
1
|
||||
};
|
||||
|
||||
let create_mmio_allocators = |start, end, num_pci_segments, alignment| {
|
||||
// Start each PCI segment mmio range on an aligned boundary
|
||||
let pci_segment_mmio_size =
|
||||
(end - start + 1) / (alignment * num_pci_segments as u64) * alignment;
|
||||
|
||||
let mut mmio_allocators = vec![];
|
||||
for i in 0..num_pci_segments as u64 {
|
||||
let mmio_start = start + i * pci_segment_mmio_size;
|
||||
let allocator = Arc::new(Mutex::new(
|
||||
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_mmio_size).unwrap(),
|
||||
));
|
||||
mmio_allocators.push(allocator)
|
||||
let mut mmio32_aperture_weights: Vec<u32> =
|
||||
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
|
||||
.take(num_pci_segments.into())
|
||||
.collect();
|
||||
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
|
||||
for pci_segment in pci_segments.iter() {
|
||||
mmio32_aperture_weights[pci_segment.pci_segment as usize] =
|
||||
pci_segment.mmio32_aperture_weight
|
||||
}
|
||||
|
||||
mmio_allocators
|
||||
};
|
||||
}
|
||||
|
||||
let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
|
||||
let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
|
||||
|
@ -1032,15 +1051,28 @@ impl DeviceManager {
|
|||
start_of_mmio32_area,
|
||||
end_of_mmio32_area,
|
||||
num_pci_segments,
|
||||
mmio32_aperture_weights,
|
||||
4 << 10,
|
||||
);
|
||||
|
||||
let mut mmio64_aperture_weights: Vec<u32> =
|
||||
std::iter::repeat(DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT)
|
||||
.take(num_pci_segments.into())
|
||||
.collect();
|
||||
if let Some(pci_segments) = &config.lock().unwrap().pci_segments {
|
||||
for pci_segment in pci_segments.iter() {
|
||||
mmio64_aperture_weights[pci_segment.pci_segment as usize] =
|
||||
pci_segment.mmio64_aperture_weight
|
||||
}
|
||||
}
|
||||
|
||||
let start_of_mmio64_area = memory_manager.lock().unwrap().start_of_device_area().0;
|
||||
let end_of_mmio64_area = memory_manager.lock().unwrap().end_of_device_area().0;
|
||||
let pci_mmio64_allocators = create_mmio_allocators(
|
||||
start_of_mmio64_area,
|
||||
end_of_mmio64_area,
|
||||
num_pci_segments,
|
||||
mmio64_aperture_weights,
|
||||
4 << 30,
|
||||
);
|
||||
|
||||
|
@ -1144,7 +1176,6 @@ impl DeviceManager {
|
|||
}
|
||||
|
||||
let device_manager = DeviceManager {
|
||||
hypervisor_type,
|
||||
address_manager: Arc::clone(&address_manager),
|
||||
console: Arc::new(Console::default()),
|
||||
interrupt_controller: None,
|
||||
|
@ -1178,10 +1209,7 @@ impl DeviceManager {
|
|||
.map_err(DeviceManagerError::EventFd)?,
|
||||
acpi_address,
|
||||
selected_segment: 0,
|
||||
serial_pty: None,
|
||||
serial_manager: None,
|
||||
console_pty: None,
|
||||
debug_console_pty: None,
|
||||
console_resize_pipe: None,
|
||||
original_termios_opt: Arc::new(Mutex::new(None)),
|
||||
virtio_mem_devices: Vec::new(),
|
||||
|
@ -1214,33 +1242,13 @@ impl DeviceManager {
|
|||
Ok(device_manager)
|
||||
}
|
||||
|
||||
pub fn serial_pty(&self) -> Option<PtyPair> {
|
||||
self.serial_pty
|
||||
.as_ref()
|
||||
.map(|pty| pty.lock().unwrap().clone())
|
||||
}
|
||||
|
||||
pub fn console_pty(&self) -> Option<PtyPair> {
|
||||
self.console_pty
|
||||
.as_ref()
|
||||
.map(|pty| pty.lock().unwrap().clone())
|
||||
}
|
||||
|
||||
pub fn debug_console_pty(&self) -> Option<PtyPair> {
|
||||
self.debug_console_pty
|
||||
.as_ref()
|
||||
.map(|pty| pty.lock().unwrap().clone())
|
||||
}
|
||||
|
||||
pub fn console_resize_pipe(&self) -> Option<Arc<File>> {
|
||||
self.console_resize_pipe.clone()
|
||||
}
|
||||
|
||||
pub fn create_devices(
|
||||
&mut self,
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
debug_console_pty: Option<PtyPair>,
|
||||
console_info: Option<ConsoleInfo>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
) -> DeviceManagerResult<()> {
|
||||
|
@ -1303,9 +1311,7 @@ impl DeviceManager {
|
|||
self.console = self.add_console_devices(
|
||||
&legacy_interrupt_manager,
|
||||
&mut virtio_devices,
|
||||
serial_pty,
|
||||
console_pty,
|
||||
debug_console_pty,
|
||||
console_info,
|
||||
console_resize_pipe,
|
||||
)?;
|
||||
|
||||
|
@ -1371,7 +1377,7 @@ impl DeviceManager {
|
|||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
self.get_msi_iova_space(),
|
||||
versioned_state_from_id(self.snapshot.as_ref(), iommu_id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), iommu_id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioIommu)?;
|
||||
|
@ -1519,7 +1525,7 @@ impl DeviceManager {
|
|||
id.clone(),
|
||||
APIC_START,
|
||||
Arc::clone(&self.msi_interrupt_manager),
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateInterruptController)?,
|
||||
|
@ -1791,7 +1797,7 @@ impl DeviceManager {
|
|||
let gpio_device = Arc::new(Mutex::new(devices::legacy::Gpio::new(
|
||||
id.clone(),
|
||||
interrupt_group,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)));
|
||||
|
||||
|
@ -1892,7 +1898,7 @@ impl DeviceManager {
|
|||
id.clone(),
|
||||
interrupt_group,
|
||||
serial_writer,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)));
|
||||
|
||||
|
@ -1949,7 +1955,7 @@ impl DeviceManager {
|
|||
interrupt_group,
|
||||
serial_writer,
|
||||
self.timestamp,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)));
|
||||
|
||||
|
@ -1986,127 +1992,50 @@ impl DeviceManager {
|
|||
Ok(serial)
|
||||
}
|
||||
|
||||
fn modify_mode<F: FnOnce(&mut termios)>(
|
||||
&mut self,
|
||||
fd: RawFd,
|
||||
f: F,
|
||||
) -> vmm_sys_util::errno::Result<()> {
|
||||
// SAFETY: safe because we check the return value of isatty.
|
||||
if unsafe { isatty(fd) } != 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// SAFETY: The following pair are safe because termios gets totally overwritten by tcgetattr
|
||||
// and we check the return result.
|
||||
let mut termios: termios = unsafe { zeroed() };
|
||||
// SAFETY: see above
|
||||
let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) };
|
||||
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.
|
||||
let ret = unsafe { tcsetattr(fd, TCSANOW, &termios as *const _) };
|
||||
if ret < 0 {
|
||||
return vmm_sys_util::errno::errno_result();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_raw_mode(&mut self, f: &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<()> {
|
||||
let seccomp_filter = get_seccomp_filter(
|
||||
&self.seccomp_action,
|
||||
Thread::PtyForeground,
|
||||
self.hypervisor_type,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self.console_resize_pipe =
|
||||
Some(Arc::new(start_sigwinch_listener(seccomp_filter, pty_sub)?));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_virtio_console_device(
|
||||
&mut self,
|
||||
virtio_devices: &mut Vec<MetaVirtioDevice>,
|
||||
console_pty: Option<PtyPair>,
|
||||
console_fd: Option<RawFd>,
|
||||
resize_pipe: Option<File>,
|
||||
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
|
||||
let console_config = self.config.lock().unwrap().console.clone();
|
||||
let endpoint = match console_config.mode {
|
||||
ConsoleOutputMode::File => {
|
||||
let file = File::create(console_config.file.as_ref().unwrap())
|
||||
.map_err(DeviceManagerError::ConsoleOutputFileOpen)?;
|
||||
Endpoint::File(file)
|
||||
if let Some(file_fd) = console_fd {
|
||||
Endpoint::File(unsafe { File::from_raw_fd(file_fd) })
|
||||
} else {
|
||||
return Err(DeviceManagerError::InvalidConsoleFd);
|
||||
}
|
||||
}
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty) = console_pty {
|
||||
self.config.lock().unwrap().console.file = Some(pty.path.clone());
|
||||
let file = pty.main.try_clone().unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(pty)));
|
||||
if let Some(pty_fd) = console_fd {
|
||||
let file = unsafe { File::from_raw_fd(pty_fd) };
|
||||
self.console_resize_pipe = resize_pipe.map(Arc::new);
|
||||
Endpoint::PtyPair(file.try_clone().unwrap(), file)
|
||||
} else {
|
||||
let (main, sub, path) =
|
||||
create_pty().map_err(DeviceManagerError::ConsolePtyOpen)?;
|
||||
self.set_raw_mode(&sub)
|
||||
.map_err(DeviceManagerError::SetPtyRaw)?;
|
||||
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.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
|
||||
Endpoint::PtyPair(file.try_clone().unwrap(), file)
|
||||
return Err(DeviceManagerError::InvalidConsoleFd);
|
||||
}
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
// Duplicating the file descriptors like this is needed as otherwise
|
||||
// they will be closed on a reboot and the numbers reused
|
||||
|
||||
// SAFETY: FFI call to dup. Trivially safe.
|
||||
let stdout = unsafe { libc::dup(libc::STDOUT_FILENO) };
|
||||
if stdout == -1 {
|
||||
return vmm_sys_util::errno::errno_result().map_err(DeviceManagerError::DupFd);
|
||||
}
|
||||
// SAFETY: stdout is valid and owned solely by us.
|
||||
let stdout = unsafe { File::from_raw_fd(stdout) };
|
||||
|
||||
// Make sure stdout is in raw mode, if it's a terminal.
|
||||
let _ = self.set_raw_mode(&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 } {
|
||||
// SAFETY: FFI call to dup. Trivially safe.
|
||||
let stdin = unsafe { libc::dup(libc::STDIN_FILENO) };
|
||||
if stdin == -1 {
|
||||
return vmm_sys_util::errno::errno_result()
|
||||
.map_err(DeviceManagerError::DupFd);
|
||||
if let Some(tty_fd) = console_fd {
|
||||
let stdout = unsafe { File::from_raw_fd(tty_fd) };
|
||||
// If an interactive TTY then we can accept input
|
||||
// SAFETY: FFI call. Trivially safe.
|
||||
if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
|
||||
// SAFETY: FFI call to dup. Trivially safe.
|
||||
let stdin = unsafe { libc::dup(libc::STDIN_FILENO) };
|
||||
if stdin == -1 {
|
||||
return vmm_sys_util::errno::errno_result()
|
||||
.map_err(DeviceManagerError::DupFd);
|
||||
}
|
||||
// SAFETY: stdin is valid and owned solely by us.
|
||||
let stdin = unsafe { File::from_raw_fd(stdin) };
|
||||
Endpoint::FilePair(stdout, stdin)
|
||||
} else {
|
||||
Endpoint::File(stdout)
|
||||
}
|
||||
// SAFETY: stdin is valid and owned solely by us.
|
||||
let stdin = unsafe { File::from_raw_fd(stdin) };
|
||||
|
||||
Endpoint::FilePair(stdout, stdin)
|
||||
} else {
|
||||
Endpoint::File(stdout)
|
||||
return Err(DeviceManagerError::InvalidConsoleFd);
|
||||
}
|
||||
}
|
||||
ConsoleOutputMode::Socket => {
|
||||
|
@ -2128,7 +2057,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
||||
|
@ -2167,38 +2096,31 @@ impl DeviceManager {
|
|||
&mut self,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
virtio_devices: &mut Vec<MetaVirtioDevice>,
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
#[cfg(target_arch = "x86_64")] debug_console_pty: Option<PtyPair>,
|
||||
#[cfg(not(target_arch = "x86_64"))] _: Option<PtyPair>,
|
||||
console_info: Option<ConsoleInfo>,
|
||||
console_resize_pipe: Option<File>,
|
||||
) -> DeviceManagerResult<Arc<Console>> {
|
||||
let serial_config = self.config.lock().unwrap().serial.clone();
|
||||
if console_info.is_none() {
|
||||
return Err(DeviceManagerError::InvalidConsoleInfo);
|
||||
}
|
||||
//SAFE: console_info is Some, so it's safe to unwrap.
|
||||
let console_info = console_info.unwrap();
|
||||
let serial_writer: Option<Box<dyn io::Write + Send>> = match serial_config.mode {
|
||||
ConsoleOutputMode::File => Some(Box::new(
|
||||
File::create(serial_config.file.as_ref().unwrap())
|
||||
.map_err(DeviceManagerError::SerialOutputFileOpen)?,
|
||||
)),
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty) = serial_pty.clone() {
|
||||
self.config.lock().unwrap().serial.file = Some(pty.path.clone());
|
||||
self.serial_pty = Some(Arc::new(Mutex::new(pty)));
|
||||
} else {
|
||||
let (main, sub, path) =
|
||||
create_pty().map_err(DeviceManagerError::SerialPtyOpen)?;
|
||||
self.set_raw_mode(&sub)
|
||||
.map_err(DeviceManagerError::SetPtyRaw)?;
|
||||
self.config.lock().unwrap().serial.file = Some(path.clone());
|
||||
self.serial_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
|
||||
ConsoleOutputMode::File | ConsoleOutputMode::Tty => {
|
||||
if console_info.serial_main_fd.is_none() {
|
||||
return Err(DeviceManagerError::InvalidConsoleInfo);
|
||||
}
|
||||
None
|
||||
// SAFETY: serial_main_fd is Some, so it's safe to unwrap.
|
||||
// SAFETY: serial_main_fd, is a valid FD, it is checked in
|
||||
// pre_create_console_devices
|
||||
Some(Box::new(unsafe {
|
||||
File::from_raw_fd(console_info.serial_main_fd.unwrap())
|
||||
}))
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
let out = stdout();
|
||||
let _ = self.set_raw_mode(&out);
|
||||
Some(Box::new(out))
|
||||
}
|
||||
ConsoleOutputMode::Off | ConsoleOutputMode::Null | ConsoleOutputMode::Socket => None,
|
||||
ConsoleOutputMode::Off
|
||||
| ConsoleOutputMode::Null
|
||||
| ConsoleOutputMode::Pty
|
||||
| ConsoleOutputMode::Socket => None,
|
||||
};
|
||||
if serial_config.mode != ConsoleOutputMode::Off {
|
||||
let serial = self.add_serial_device(interrupt_manager, serial_writer)?;
|
||||
|
@ -2206,7 +2128,7 @@ impl DeviceManager {
|
|||
ConsoleOutputMode::Pty | ConsoleOutputMode::Tty | ConsoleOutputMode::Socket => {
|
||||
let serial_manager = SerialManager::new(
|
||||
serial,
|
||||
self.serial_pty.clone(),
|
||||
console_info.serial_main_fd,
|
||||
serial_config.mode,
|
||||
serial_config.socket,
|
||||
)
|
||||
|
@ -2231,43 +2153,34 @@ impl DeviceManager {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let debug_console_config = self.config.lock().unwrap().debug_console.clone();
|
||||
let debug_console_writer: Option<Box<dyn io::Write + Send>> = match debug_console_config
|
||||
.mode
|
||||
{
|
||||
ConsoleOutputMode::File => Some(Box::new(
|
||||
File::create(debug_console_config.file.as_ref().unwrap())
|
||||
.map_err(DeviceManagerError::DebugconOutputFileOpen)?,
|
||||
)),
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty) = debug_console_pty {
|
||||
self.config.lock().unwrap().debug_console.file = Some(pty.path.clone());
|
||||
self.debug_console_pty = Some(Arc::new(Mutex::new(pty)));
|
||||
} else {
|
||||
let (main, sub, path) =
|
||||
create_pty().map_err(DeviceManagerError::DebugconPtyOpen)?;
|
||||
self.set_raw_mode(&sub)
|
||||
.map_err(DeviceManagerError::SetPtyRaw)?;
|
||||
self.config.lock().unwrap().debug_console.file = Some(path.clone());
|
||||
self.debug_console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
|
||||
let debug_console_writer: Option<Box<dyn io::Write + Send>> =
|
||||
match debug_console_config.mode {
|
||||
ConsoleOutputMode::File | ConsoleOutputMode::Tty => {
|
||||
if console_info.debug_main_fd.is_none() {
|
||||
return Err(DeviceManagerError::InvalidConsoleInfo);
|
||||
}
|
||||
// SAFETY: debug_main_fd is Some, so it's safe to unwrap.
|
||||
// SAFETY: debug_main_fd, is a valid FD, it is checked in
|
||||
// pre_create_console_devices
|
||||
Some(Box::new(unsafe {
|
||||
File::from_raw_fd(console_info.debug_main_fd.unwrap())
|
||||
}))
|
||||
}
|
||||
None
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
let out = stdout();
|
||||
let _ = self.set_raw_mode(&out);
|
||||
Some(Box::new(out))
|
||||
}
|
||||
ConsoleOutputMode::Off | ConsoleOutputMode::Null | ConsoleOutputMode::Socket => {
|
||||
None
|
||||
}
|
||||
};
|
||||
ConsoleOutputMode::Off
|
||||
| ConsoleOutputMode::Null
|
||||
| ConsoleOutputMode::Pty
|
||||
| ConsoleOutputMode::Socket => None,
|
||||
};
|
||||
if let Some(writer) = debug_console_writer {
|
||||
let _ = self.add_debug_console_device(writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
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_info.console_main_fd,
|
||||
console_resize_pipe,
|
||||
)?;
|
||||
|
||||
Ok(Arc::new(Console { console_resizer }))
|
||||
}
|
||||
|
@ -2362,8 +2275,6 @@ impl DeviceManager {
|
|||
|
||||
info!("Creating virtio-block device: {:?}", disk_cfg);
|
||||
|
||||
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
|
||||
|
||||
let (virtio_device, migratable_device) = if disk_cfg.vhost_user {
|
||||
let socket = disk_cfg.vhost_socket.as_ref().unwrap().clone();
|
||||
let vu_cfg = VhostUserConfig {
|
||||
|
@ -2380,9 +2291,7 @@ impl DeviceManager {
|
|||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
self.force_iommu,
|
||||
snapshot
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
) {
|
||||
Ok(vub_device) => vub_device,
|
||||
|
@ -2542,9 +2451,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
snapshot
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
queue_affinity,
|
||||
)
|
||||
|
@ -2601,8 +2508,6 @@ impl DeviceManager {
|
|||
};
|
||||
info!("Creating virtio-net device: {:?}", net_cfg);
|
||||
|
||||
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
|
||||
|
||||
let (virtio_device, migratable_device) = if net_cfg.vhost_user {
|
||||
let socket = net_cfg.vhost_socket.as_ref().unwrap().clone();
|
||||
let vu_cfg = VhostUserConfig {
|
||||
|
@ -2626,9 +2531,7 @@ impl DeviceManager {
|
|||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
self.force_iommu,
|
||||
snapshot
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
net_cfg.offload_tso,
|
||||
net_cfg.offload_ufo,
|
||||
|
@ -2646,11 +2549,8 @@ impl DeviceManager {
|
|||
vhost_user_net as Arc<Mutex<dyn Migratable>>,
|
||||
)
|
||||
} else {
|
||||
let state = snapshot
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
let state = state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?;
|
||||
|
||||
let virtio_net = if let Some(ref tap_if_name) = net_cfg.tap {
|
||||
Arc::new(Mutex::new(
|
||||
virtio_devices::Net::new(
|
||||
|
@ -2784,7 +2684,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioRng)?,
|
||||
|
@ -2840,7 +2740,7 @@ impl DeviceManager {
|
|||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
self.force_iommu,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioFs)?,
|
||||
|
@ -3024,7 +2924,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioPmem)?,
|
||||
|
@ -3096,7 +2996,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioVsock)?,
|
||||
|
@ -3156,7 +3056,7 @@ impl DeviceManager {
|
|||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
virtio_mem_zone.blocks_state().clone(),
|
||||
versioned_state_from_id(self.snapshot.as_ref(), memory_zone_id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), memory_zone_id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioMem)?,
|
||||
|
@ -3208,7 +3108,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioBalloon)?,
|
||||
|
@ -3252,7 +3152,7 @@ impl DeviceManager {
|
|||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioWatchdog)?,
|
||||
|
@ -3299,7 +3199,7 @@ impl DeviceManager {
|
|||
device_path,
|
||||
self.memory_manager.lock().unwrap().guest_memory(),
|
||||
vdpa_cfg.num_queues as u16,
|
||||
versioned_state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
state_from_id(self.snapshot.as_ref(), id.as_str())
|
||||
.map_err(DeviceManagerError::RestoreGetState)?,
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVdpa)?,
|
||||
|
@ -5010,3 +4910,60 @@ impl Drop for DeviceManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_mmio_allocators() {
|
||||
let res = create_mmio_allocators(0x100000, 0x400000, 1, vec![1], 4 << 10);
|
||||
assert_eq!(res.len(), 1);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().base(),
|
||||
vm_memory::GuestAddress(0x100000)
|
||||
);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().end(),
|
||||
vm_memory::GuestAddress(0x3fffff)
|
||||
);
|
||||
|
||||
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![1, 1], 4 << 10);
|
||||
assert_eq!(res.len(), 2);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().base(),
|
||||
vm_memory::GuestAddress(0x100000)
|
||||
);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().end(),
|
||||
vm_memory::GuestAddress(0x27ffff)
|
||||
);
|
||||
assert_eq!(
|
||||
res[1].lock().unwrap().base(),
|
||||
vm_memory::GuestAddress(0x280000)
|
||||
);
|
||||
assert_eq!(
|
||||
res[1].lock().unwrap().end(),
|
||||
vm_memory::GuestAddress(0x3fffff)
|
||||
);
|
||||
|
||||
let res = create_mmio_allocators(0x100000, 0x400000, 2, vec![2, 1], 4 << 10);
|
||||
assert_eq!(res.len(), 2);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().base(),
|
||||
vm_memory::GuestAddress(0x100000)
|
||||
);
|
||||
assert_eq!(
|
||||
res[0].lock().unwrap().end(),
|
||||
vm_memory::GuestAddress(0x2fffff)
|
||||
);
|
||||
assert_eq!(
|
||||
res[1].lock().unwrap().base(),
|
||||
vm_memory::GuestAddress(0x300000)
|
||||
);
|
||||
assert_eq!(
|
||||
res[1].lock().unwrap().end(),
|
||||
vm_memory::GuestAddress(0x3fffff)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,15 @@
|
|||
use crate::cpu::CpuManager;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
use crate::igvm::loader::Loader;
|
||||
use crate::igvm::IgvmLoadedInfo;
|
||||
use crate::igvm::{BootPageAcceptance, StartupMemoryType, HV_PAGE_SIZE};
|
||||
use crate::igvm::{
|
||||
loader::Loader, BootPageAcceptance, IgvmLoadedInfo, StartupMemoryType, HV_PAGE_SIZE,
|
||||
};
|
||||
use crate::memory_manager::MemoryManager;
|
||||
use igvm_defs::IgvmPageDataType;
|
||||
use igvm_defs::IgvmPlatformType;
|
||||
use igvm_parser::IgvmDirectiveHeader;
|
||||
use igvm_parser::IgvmFile;
|
||||
use igvm_parser::IgvmPlatformHeader;
|
||||
use igvm_parser::IsolationType;
|
||||
|
||||
use igvm_defs::IGVM_VHS_PARAMETER;
|
||||
use igvm_defs::IGVM_VHS_PARAMETER_INSERT;
|
||||
|
||||
use igvm_parser::snp_defs::SevVmsa;
|
||||
pub use mshv_bindings::*;
|
||||
use igvm::{snp_defs::SevVmsa, IgvmDirectiveHeader, IgvmFile, IgvmPlatformHeader, IsolationType};
|
||||
use igvm_defs::{
|
||||
IgvmPageDataType, IgvmPlatformType, IGVM_VHS_PARAMETER, IGVM_VHS_PARAMETER_INSERT,
|
||||
};
|
||||
use mshv_bindings::*;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CString;
|
||||
use std::io::Read;
|
||||
|
@ -42,7 +35,7 @@ pub enum Error {
|
|||
#[error("failed to read igvm file")]
|
||||
Igvm(#[source] std::io::Error),
|
||||
#[error("invalid igvm file")]
|
||||
InvalidIgvmFile(#[source] igvm_parser::Error),
|
||||
InvalidIgvmFile(#[source] igvm::Error),
|
||||
#[error("invalid guest memory map")]
|
||||
InvalidGuestMemmap(#[source] arch::Error),
|
||||
#[error("loader error")]
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
pub mod igvm_loader;
|
||||
mod loader;
|
||||
use igvm::snp_defs::SevVmsa;
|
||||
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
|
||||
use igvm_parser::snp_defs::SevVmsa;
|
||||
use zerocopy::FromZeroes;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -28,6 +28,7 @@ use anyhow::anyhow;
|
|||
#[cfg(feature = "dbus_api")]
|
||||
use api::dbus::{DBusApiOptions, DBusApiShutdownChannels};
|
||||
use api::http::HttpApiHandle;
|
||||
use console_devices::{pre_create_console_devices, ConsoleInfo};
|
||||
use libc::{tcsetattr, termios, EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW};
|
||||
use memory_manager::MemoryManagerSnapshotData;
|
||||
use pci::PciBdf;
|
||||
|
@ -63,6 +64,7 @@ mod acpi;
|
|||
pub mod api;
|
||||
mod clone3;
|
||||
pub mod config;
|
||||
pub mod console_devices;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
mod coredump;
|
||||
pub mod cpu;
|
||||
|
@ -548,6 +550,8 @@ pub struct Vmm {
|
|||
signals: Option<Handle>,
|
||||
threads: Vec<thread::JoinHandle<()>>,
|
||||
original_termios_opt: Arc<Mutex<Option<termios>>>,
|
||||
console_resize_pipe: Option<File>,
|
||||
console_info: Option<ConsoleInfo>,
|
||||
}
|
||||
|
||||
impl Vmm {
|
||||
|
@ -682,6 +686,8 @@ impl Vmm {
|
|||
signals: None,
|
||||
threads: vec![],
|
||||
original_termios_opt: Arc::new(Mutex::new(None)),
|
||||
console_resize_pipe: None,
|
||||
console_info: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -805,8 +811,6 @@ impl Vmm {
|
|||
timestamp,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Some(snapshot),
|
||||
)
|
||||
|
@ -1208,6 +1212,8 @@ impl RequestHandler for Vmm {
|
|||
// The VM will be created when being asked to boot it.
|
||||
if self.vm_config.is_none() {
|
||||
self.vm_config = Some(config);
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(VmError::VmAlreadyCreated)
|
||||
|
@ -1225,6 +1231,12 @@ impl RequestHandler for Vmm {
|
|||
return Err(VmError::VmMissingConfig);
|
||||
};
|
||||
|
||||
// console_info is set to None, if the VM was shutdown. Check here and re-create if needed.
|
||||
if self.console_info.is_none() {
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
}
|
||||
|
||||
// Create a new VM if we don't have one yet.
|
||||
if self.vm.is_none() {
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
|
@ -1249,9 +1261,7 @@ impl RequestHandler for Vmm {
|
|||
&self.seccomp_action,
|
||||
self.hypervisor.clone(),
|
||||
activate_evt,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
self.console_info.clone(),
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
None,
|
||||
|
@ -1294,6 +1304,7 @@ impl RequestHandler for Vmm {
|
|||
}
|
||||
|
||||
fn vm_snapshot(&mut self, destination_url: &str) -> result::Result<(), VmError> {
|
||||
let _ = self.console_info.take();
|
||||
if let Some(ref mut vm) = self.vm {
|
||||
vm.snapshot()
|
||||
.map_err(VmError::Snapshot)
|
||||
|
@ -1330,6 +1341,10 @@ impl RequestHandler for Vmm {
|
|||
.map_err(VmError::Restore)?;
|
||||
|
||||
self.vm_config = Some(Arc::clone(&vm_config));
|
||||
if self.console_info.is_none() {
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
}
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
|
@ -1354,8 +1369,6 @@ impl RequestHandler for Vmm {
|
|||
activate_evt,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Some(snapshot),
|
||||
Some(source_url),
|
||||
|
@ -1381,6 +1394,7 @@ impl RequestHandler for Vmm {
|
|||
}
|
||||
|
||||
fn vm_shutdown(&mut self) -> result::Result<(), VmError> {
|
||||
let _ = self.console_info.take();
|
||||
let r = if let Some(ref mut vm) = self.vm.take() {
|
||||
vm.shutdown()
|
||||
} else {
|
||||
|
@ -1398,27 +1412,21 @@ impl RequestHandler for Vmm {
|
|||
event!("vm", "rebooting");
|
||||
|
||||
// First we stop the current VM
|
||||
let (config, serial_pty, console_pty, debug_console_pty, console_resize_pipe) =
|
||||
if let Some(mut vm) = self.vm.take() {
|
||||
let config = vm.get_config();
|
||||
let serial_pty = vm.serial_pty();
|
||||
let console_pty = vm.console_pty();
|
||||
let debug_console_pty = vm.debug_console_pty();
|
||||
let console_resize_pipe = vm
|
||||
.console_resize_pipe()
|
||||
.as_ref()
|
||||
.map(|pipe| pipe.try_clone().unwrap());
|
||||
vm.shutdown()?;
|
||||
(
|
||||
config,
|
||||
serial_pty,
|
||||
console_pty,
|
||||
debug_console_pty,
|
||||
console_resize_pipe,
|
||||
)
|
||||
} else {
|
||||
return Err(VmError::VmNotCreated);
|
||||
};
|
||||
let (config, console_resize_pipe) = if let Some(mut vm) = self.vm.take() {
|
||||
let config = vm.get_config();
|
||||
let console_resize_pipe = vm
|
||||
.console_resize_pipe()
|
||||
.as_ref()
|
||||
.map(|pipe| pipe.try_clone().unwrap());
|
||||
vm.shutdown()?;
|
||||
(config, console_resize_pipe)
|
||||
} else {
|
||||
return Err(VmError::VmNotCreated);
|
||||
};
|
||||
|
||||
// vm.shutdown() closes most of the console devices, so set console_info to None
|
||||
// so that the closed FDs are not reused.
|
||||
let _ = self.console_info.take();
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
|
@ -1439,6 +1447,9 @@ impl RequestHandler for Vmm {
|
|||
warn!("Spurious second reset event received. Ignoring.");
|
||||
}
|
||||
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
|
||||
// Then we create the new VM
|
||||
let mut vm = Vm::new(
|
||||
config,
|
||||
|
@ -1449,9 +1460,7 @@ impl RequestHandler for Vmm {
|
|||
&self.seccomp_action,
|
||||
self.hypervisor.clone(),
|
||||
activate_evt,
|
||||
serial_pty,
|
||||
console_pty,
|
||||
debug_console_pty,
|
||||
self.console_info.clone(),
|
||||
console_resize_pipe,
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
None,
|
||||
|
@ -2151,6 +2160,7 @@ mod unit_tests {
|
|||
watchdog: false,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb: false,
|
||||
pci_segments: None,
|
||||
platform: None,
|
||||
tpm: None,
|
||||
preserved_fds: None,
|
||||
|
|
|
@ -39,8 +39,6 @@ use std::result;
|
|||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{ffi, thread};
|
||||
use tracer::trace_scoped;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_devices::BlocksState;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use vm_allocator::GsiApic;
|
||||
|
@ -55,7 +53,7 @@ use vm_memory::{
|
|||
};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRange, protocol::MemoryRangeTable, Migratable, MigratableError, Pausable,
|
||||
Snapshot, SnapshotData, Snapshottable, Transportable, VersionMapped,
|
||||
Snapshot, SnapshotData, Snapshottable, Transportable,
|
||||
};
|
||||
|
||||
pub const MEMORY_MANAGER_ACPI_SIZE: usize = 0x18;
|
||||
|
@ -82,7 +80,7 @@ const PLATFORM_DEVICE_AREA_SIZE: u64 = 1 << 20;
|
|||
|
||||
const MAX_PREFAULT_THREAD_COUNT: usize = 16;
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
struct HotPlugState {
|
||||
base: u64,
|
||||
length: u64,
|
||||
|
@ -143,7 +141,7 @@ impl MemoryZone {
|
|||
|
||||
pub type MemoryZones = HashMap<String, MemoryZone>;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
struct GuestRamMapping {
|
||||
slot: u32,
|
||||
gpa: u64,
|
||||
|
@ -153,7 +151,7 @@ struct GuestRamMapping {
|
|||
file_offset: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
struct ArchMemRegion {
|
||||
base: u64,
|
||||
size: usize,
|
||||
|
@ -1269,7 +1267,7 @@ impl MemoryManager {
|
|||
memory_file_path.push(String::from(SNAPSHOT_FILENAME));
|
||||
|
||||
let mem_snapshot: MemoryManagerSnapshotData =
|
||||
snapshot.to_versioned_state().map_err(Error::Restore)?;
|
||||
snapshot.to_state().map_err(Error::Restore)?;
|
||||
|
||||
let mm = MemoryManager::new(
|
||||
vm,
|
||||
|
@ -2628,7 +2626,7 @@ impl Aml for MemoryManager {
|
|||
|
||||
impl Pausable for MemoryManager {}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Versionize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct MemoryManagerSnapshotData {
|
||||
memory_ranges: MemoryRangeTable,
|
||||
guest_ram_mappings: Vec<GuestRamMapping>,
|
||||
|
@ -2642,8 +2640,6 @@ pub struct MemoryManagerSnapshotData {
|
|||
next_hotplug_slot: usize,
|
||||
}
|
||||
|
||||
impl VersionMapped for MemoryManagerSnapshotData {}
|
||||
|
||||
impl Snapshottable for MemoryManager {
|
||||
fn id(&self) -> String {
|
||||
MEMORY_MANAGER_SNAPSHOT_ID.to_string()
|
||||
|
@ -2662,7 +2658,7 @@ impl Snapshottable for MemoryManager {
|
|||
// memory range content for the ranges requiring it.
|
||||
self.snapshot_memory_ranges = memory_ranges;
|
||||
|
||||
Ok(Snapshot::from_data(SnapshotData::new_from_versioned_state(
|
||||
Ok(Snapshot::from_data(SnapshotData::new_from_state(
|
||||
&self.snapshot_data(),
|
||||
)?))
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ mod mshv {
|
|||
pub const MSHV_GET_VP_STATE: u64 = 0xc010_b80a;
|
||||
pub const MSHV_SET_VP_STATE: u64 = 0xc010_b80b;
|
||||
pub const MSHV_SET_PARTITION_PROPERTY: u64 = 0x4010_b80c;
|
||||
pub const MSHV_GET_PARTITION_PROPERTY: u64 = 0xc010_b80d;
|
||||
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;
|
||||
|
@ -211,6 +212,12 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result<Vec<SeccompRule>, Backe
|
|||
Eq,
|
||||
MSHV_SET_PARTITION_PROPERTY
|
||||
)?],
|
||||
and![Cond::new(
|
||||
1,
|
||||
ArgLen::Dword,
|
||||
Eq,
|
||||
MSHV_GET_PARTITION_PROPERTY
|
||||
)?],
|
||||
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)?],
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
//
|
||||
|
||||
use crate::config::ConsoleOutputMode;
|
||||
use crate::device_manager::PtyPair;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use devices::legacy::Pl011;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -14,6 +13,7 @@ use serial_buffer::SerialBuffer;
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::net::Shutdown;
|
||||
use std::os::fd::RawFd;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::panic::AssertUnwindSafe;
|
||||
|
@ -119,7 +119,7 @@ impl SerialManager {
|
|||
pub fn new(
|
||||
#[cfg(target_arch = "x86_64")] serial: Arc<Mutex<Serial>>,
|
||||
#[cfg(target_arch = "aarch64")] serial: Arc<Mutex<Pl011>>,
|
||||
pty_pair: Option<Arc<Mutex<PtyPair>>>,
|
||||
main_fd: Option<RawFd>,
|
||||
mode: ConsoleOutputMode,
|
||||
socket: Option<PathBuf>,
|
||||
) -> Result<Option<Self>> {
|
||||
|
@ -127,13 +127,8 @@ impl SerialManager {
|
|||
|
||||
let in_file = match mode {
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty_pair) = pty_pair {
|
||||
pty_pair
|
||||
.lock()
|
||||
.unwrap()
|
||||
.main
|
||||
.try_clone()
|
||||
.map_err(Error::FileClone)?
|
||||
if let Some(pty_main) = main_fd {
|
||||
unsafe { File::from_raw_fd(pty_main) }
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -161,12 +156,12 @@ impl SerialManager {
|
|||
}
|
||||
}
|
||||
ConsoleOutputMode::Socket => {
|
||||
if let Some(path_in_socket) = socket {
|
||||
socket_path = Some(path_in_socket.clone());
|
||||
let listener = UnixListener::bind(path_in_socket.as_path())
|
||||
.map_err(Error::BindUnixSocket)?;
|
||||
// SAFETY: listener is valid and will return valid fd
|
||||
unsafe { File::from_raw_fd(listener.into_raw_fd()) }
|
||||
if let Some(socket_fd) = main_fd {
|
||||
if let Some(path_in_socket) = socket {
|
||||
socket_path = Some(path_in_socket.clone());
|
||||
}
|
||||
// SAFETY: socket_fd is valid and will return a valid File
|
||||
unsafe { File::from_raw_fd(socket_fd) }
|
||||
} else {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::clone3::{clone3, clone_args, CLONE_CLEAR_SIGHAND};
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use arch::_NSIG;
|
||||
use hypervisor::HypervisorType;
|
||||
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, SIGCHLD, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY,
|
||||
};
|
||||
use seccompiler::{apply_filter, BpfProgram};
|
||||
use seccompiler::{apply_filter, BpfProgram, SeccompAction};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs::{read_dir, File};
|
||||
|
@ -256,3 +258,16 @@ pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io:
|
|||
|
||||
Ok(rx)
|
||||
}
|
||||
|
||||
pub fn listen_for_sigwinch_on_tty(
|
||||
pty_sub: File,
|
||||
seccomp_action: &SeccompAction,
|
||||
hypervisor_type: HypervisorType,
|
||||
) -> std::io::Result<File> {
|
||||
let seccomp_filter =
|
||||
get_seccomp_filter(seccomp_action, Thread::PtyForeground, hypervisor_type).unwrap();
|
||||
|
||||
let console_resize_pipe = start_sigwinch_listener(seccomp_filter, pty_sub)?;
|
||||
|
||||
Ok(console_resize_pipe)
|
||||
}
|
||||
|
|
|
@ -16,12 +16,13 @@ use crate::config::{
|
|||
UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig,
|
||||
};
|
||||
use crate::config::{NumaConfig, PayloadConfig};
|
||||
use crate::console_devices::{ConsoleDeviceError, ConsoleInfo};
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use crate::coredump::{
|
||||
CpuElf64Writable, DumpState, Elf64Writable, GuestDebuggable, GuestDebuggableError, NoteDescType,
|
||||
};
|
||||
use crate::cpu;
|
||||
use crate::device_manager::{DeviceManager, DeviceManagerError, PtyPair};
|
||||
use crate::device_manager::{DeviceManager, DeviceManagerError};
|
||||
use crate::device_tree::DeviceTree;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload};
|
||||
|
@ -30,7 +31,7 @@ use crate::igvm::igvm_loader;
|
|||
use crate::memory_manager::{
|
||||
Error as MemoryManagerError, MemoryManager, MemoryManagerSnapshotData,
|
||||
};
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::migration::get_vm_snapshot;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use crate::migration::url_to_file;
|
||||
|
@ -94,7 +95,7 @@ use vm_memory::{
|
|||
use vm_migration::protocol::{Request, Response, Status};
|
||||
use vm_migration::{
|
||||
protocol::MemoryRangeTable, snapshot_from_id, Migratable, MigratableError, Pausable, Snapshot,
|
||||
SnapshotData, Snapshottable, Transportable,
|
||||
Snapshottable, Transportable,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
|
||||
|
@ -319,6 +320,9 @@ pub enum Error {
|
|||
|
||||
#[error("Error injecting NMI")]
|
||||
ErrorNmi,
|
||||
|
||||
#[error("Error creating console devices")]
|
||||
CreateConsoleDevices(ConsoleDeviceError),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
|
@ -457,7 +461,7 @@ pub struct Vm {
|
|||
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
|
||||
// The hypervisor abstracted virtual machine.
|
||||
vm: Arc<dyn hypervisor::Vm>,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
saved_clock: Option<hypervisor::ClockData>,
|
||||
numa_nodes: NumaNodes,
|
||||
#[cfg_attr(any(not(feature = "kvm"), target_arch = "aarch64"), allow(dead_code))]
|
||||
|
@ -481,9 +485,7 @@ impl Vm {
|
|||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
activate_evt: EventFd,
|
||||
timestamp: Instant,
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
debug_console_pty: Option<PtyPair>,
|
||||
console_info: Option<ConsoleInfo>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios: Arc<Mutex<Option<termios>>>,
|
||||
snapshot: Option<Snapshot>,
|
||||
|
@ -620,7 +622,6 @@ impl Vm {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
io_bus,
|
||||
mmio_bus,
|
||||
hypervisor.hypervisor_type(),
|
||||
vm.clone(),
|
||||
config.clone(),
|
||||
memory_manager.clone(),
|
||||
|
@ -641,13 +642,7 @@ impl Vm {
|
|||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.create_devices(
|
||||
serial_pty,
|
||||
console_pty,
|
||||
debug_console_pty,
|
||||
console_resize_pipe,
|
||||
original_termios,
|
||||
)
|
||||
.create_devices(console_info, console_resize_pipe, original_termios)
|
||||
.map_err(Error::DeviceManager)?;
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
|
@ -671,7 +666,7 @@ impl Vm {
|
|||
.transpose()
|
||||
.map_err(Error::InitramfsFile)?;
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let saved_clock = if let Some(snapshot) = snapshot.as_ref() {
|
||||
let vm_snapshot = get_vm_snapshot(snapshot).map_err(Error::Restore)?;
|
||||
vm_snapshot.clock
|
||||
|
@ -696,7 +691,7 @@ impl Vm {
|
|||
cpu_manager,
|
||||
memory_manager,
|
||||
vm,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
saved_clock,
|
||||
numa_nodes,
|
||||
hypervisor,
|
||||
|
@ -798,9 +793,7 @@ impl Vm {
|
|||
seccomp_action: &SeccompAction,
|
||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
activate_evt: EventFd,
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
debug_console_pty: Option<PtyPair>,
|
||||
console_info: Option<ConsoleInfo>,
|
||||
console_resize_pipe: Option<File>,
|
||||
original_termios: Arc<Mutex<Option<termios>>>,
|
||||
snapshot: Option<Snapshot>,
|
||||
|
@ -878,9 +871,7 @@ impl Vm {
|
|||
hypervisor,
|
||||
activate_evt,
|
||||
timestamp,
|
||||
serial_pty,
|
||||
console_pty,
|
||||
debug_console_pty,
|
||||
console_info,
|
||||
console_resize_pipe,
|
||||
original_termios,
|
||||
snapshot,
|
||||
|
@ -1356,18 +1347,6 @@ impl Vm {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn serial_pty(&self) -> Option<PtyPair> {
|
||||
self.device_manager.lock().unwrap().serial_pty()
|
||||
}
|
||||
|
||||
pub fn console_pty(&self) -> Option<PtyPair> {
|
||||
self.device_manager.lock().unwrap().console_pty()
|
||||
}
|
||||
|
||||
pub fn debug_console_pty(&self) -> Option<PtyPair> {
|
||||
self.device_manager.lock().unwrap().debug_console_pty()
|
||||
}
|
||||
|
||||
pub fn console_resize_pipe(&self) -> Option<Arc<File>> {
|
||||
self.device_manager.lock().unwrap().console_resize_pipe()
|
||||
}
|
||||
|
@ -2468,7 +2447,7 @@ impl Pausable for Vm {
|
|||
.valid_transition(new_state)
|
||||
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let mut clock = self
|
||||
.vm
|
||||
|
@ -2506,7 +2485,7 @@ impl Pausable for Vm {
|
|||
.map_err(|e| MigratableError::Resume(anyhow!("Invalid transition: {:?}", e)))?;
|
||||
|
||||
self.cpu_manager.lock().unwrap().resume()?;
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
if let Some(clock) = &self.saved_clock {
|
||||
self.vm.set_clock(clock).map_err(|e| {
|
||||
|
@ -2525,7 +2504,7 @@ impl Pausable for Vm {
|
|||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VmSnapshot {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub clock: Option<hypervisor::ClockData>,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
pub common_cpuid: Vec<hypervisor::arch::x86::CpuIdEntry>,
|
||||
|
@ -2579,15 +2558,14 @@ impl Snapshottable for Vm {
|
|||
})?
|
||||
};
|
||||
|
||||
let vm_snapshot_data = serde_json::to_vec(&VmSnapshot {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
let vm_snapshot_state = VmSnapshot {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
clock: self.saved_clock,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
common_cpuid,
|
||||
})
|
||||
.map_err(|e| MigratableError::Snapshot(e.into()))?;
|
||||
};
|
||||
|
||||
let mut vm_snapshot = Snapshot::from_data(SnapshotData(vm_snapshot_data));
|
||||
let mut vm_snapshot = Snapshot::new_from_state(&vm_snapshot_state)?;
|
||||
|
||||
let (id, snapshot) = {
|
||||
let mut cpu_manager = self.cpu_manager.lock().unwrap();
|
||||
|
@ -3247,17 +3225,11 @@ pub fn test_vm() {
|
|||
|
||||
loop {
|
||||
match vcpu.run().expect("run failed") {
|
||||
VmExit::IoOut(addr, data) => {
|
||||
println!(
|
||||
"IO out -- addr: {:#x} data [{:?}]",
|
||||
addr,
|
||||
str::from_utf8(data).unwrap()
|
||||
);
|
||||
}
|
||||
VmExit::Reset => {
|
||||
println!("HLT");
|
||||
break;
|
||||
}
|
||||
VmExit::Ignore => {}
|
||||
r => panic!("unexpected exit reason: {r:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,22 @@ pub struct PlatformConfig {
|
|||
pub sev_snp: bool,
|
||||
}
|
||||
|
||||
pub const DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT: u32 = 1;
|
||||
|
||||
fn default_pci_segment_aperture_weight() -> u32 {
|
||||
DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct PciSegmentConfig {
|
||||
#[serde(default)]
|
||||
pub pci_segment: u16,
|
||||
#[serde(default = "default_pci_segment_aperture_weight")]
|
||||
pub mmio32_aperture_weight: u32,
|
||||
#[serde(default = "default_pci_segment_aperture_weight")]
|
||||
pub mmio64_aperture_weight: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct MemoryZoneConfig {
|
||||
pub id: String,
|
||||
|
@ -620,6 +636,7 @@ pub struct VmConfig {
|
|||
#[cfg(feature = "guest_debug")]
|
||||
#[serde(default)]
|
||||
pub gdb: bool,
|
||||
pub pci_segments: Option<Vec<PciSegmentConfig>>,
|
||||
pub platform: Option<PlatformConfig>,
|
||||
pub tpm: Option<TpmConfig>,
|
||||
// Preserved FDs are the ones that share the same life-time as its holding
|
||||
|
|
Loading…
Reference in New Issue