diff --git a/.buildkite/common.py b/.buildkite/common.py index 57a46f945d0..fc74a32e65f 100644 --- a/.buildkite/common.py +++ b/.buildkite/common.py @@ -16,9 +16,8 @@ # fmt: off DEFAULT_INSTANCES = [ - "c5n.metal", # Intel Skylake "m5n.metal", # Intel Cascade Lake - "m6i.metal", # Intel Icelake + "m6i.metal", # Intel Ice Lake "m7i.metal-24xl", # Intel Sapphire Rapids "m7i.metal-48xl", # Intel Sapphire Rapids "m6a.metal", # AMD Milan @@ -79,6 +78,10 @@ def group(label, command, instances, platforms, **kwargs): """ # Use the 1st character of the group name (should be an emoji) label1 = label[0] + # if the emoji is in the form ":emoji:", pick the entire slug + if label.startswith(":") and ":" in label[1:]: + label1 = label[: label.index(":", 1) + 1] + steps = [] commands = command if isinstance(command, str): @@ -272,11 +275,11 @@ def __init__(self, with_build_step=True, **kwargs): self.per_arch["instances"] = ["m6i.metal", "m7g.metal"] self.per_arch["platforms"] = [("al2023", "linux_6.1")] self.binary_dir = args.binary_dir - # Build sharing - if with_build_step: + # Build sharing, if a binary dir wasn't already supplied + if not args.binary_dir and with_build_step: build_cmds, self.shared_build = shared_build() self.build_group_per_arch( - "🏗️ Build", build_cmds, depends_on_build=False, set_key=True + "🏗️ Build", build_cmds, depends_on_build=False, set_key=self.shared_build ) else: self.shared_build = None @@ -314,9 +317,25 @@ def _adapt_group(self, group): for step in group["steps"]: step["command"] = prepend + step["command"] if self.shared_build is not None: - step["depends_on"] = self.build_key( - get_arch_for_instance(step["agents"]["instance"]) - ) + if "depends_on" not in step: + step["depends_on"] = [] + elif isinstance(step["depends_on"], str): + step["depends_on"] = [step["depends_on"]] + elif isinstance(step["depends_on"], list): + pass + else: + raise ValueError( + f"depends_on should be a string or a list but is {type(step['depends_on'])}" + ) + + step["depends_on"].append(self.shared_build) + step["depends_on"] = [ + self.build_key( + dep, get_arch_for_instance(step["agents"]["instance"]) + ) + for dep in step["depends_on"] + ] + return group def build_group(self, *args, **kwargs): @@ -332,9 +351,9 @@ def build_group(self, *args, **kwargs): group(*args, **combined), depends_on_build=depends_on_build ) - def build_key(self, arch): + def build_key(self, key, arch): """Return the Buildkite key for the build step, for the specified arch""" - return self.shared_build.replace("$(uname -m)", arch).replace(".tar.gz", "") + return key.replace("$(uname -m)", arch).replace(".tar.gz", "") def build_group_per_arch(self, label, *args, **kwargs): """ @@ -342,7 +361,7 @@ def build_group_per_arch(self, label, *args, **kwargs): kwargs consumed by this method and not passed down to `group`: - `depends_on_build` (default: `True`): Whether the steps in this group depend on the artifacts from the shared compilation steps - - `set_key`: If True, causes the generated steps to have a "key" field + - `set_key`: If a string, causes the generated steps to have a "key" field replacing "$(uname -m)" with arch and removing trailing tar.gz """ depends_on_build = kwargs.pop("depends_on_build", True) set_key = kwargs.pop("set_key", None) @@ -351,7 +370,7 @@ def build_group_per_arch(self, label, *args, **kwargs): if set_key: for step in grp["steps"]: step["key"] = self.build_key( - get_arch_for_instance(step["agents"]["instance"]) + set_key, get_arch_for_instance(step["agents"]["instance"]) ) return self.add_step(grp, depends_on_build=depends_on_build) diff --git a/.buildkite/pipeline_coverage.py b/.buildkite/pipeline_coverage.py new file mode 100755 index 00000000000..8ca73591c00 --- /dev/null +++ b/.buildkite/pipeline_coverage.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Generate Buildkite pipelines dynamically""" + +from common import BKPipeline + +pipeline = BKPipeline(with_build_step=False) + +pipeline.build_group( + ":coverage: Coverage", + pipeline.devtool_test( + devtool_opts="--no-build", + pytest_opts="integration_tests/build/test_coverage.py", + ), +) +print(pipeline.to_json()) diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py index 312f9061ed1..f984f85648e 100755 --- a/.buildkite/pipeline_cpu_template.py +++ b/.buildkite/pipeline_cpu_template.py @@ -27,7 +27,6 @@ class BkStep(str, Enum): ], BkStep.LABEL: "📖 rdmsr", "instances": [ - "c5n.metal", "m5n.metal", "m6i.metal", "m7i.metal-24xl", @@ -63,12 +62,10 @@ class BkStep(str, Enum): BkStep.TIMEOUT: 30, }, "cross_instances": { - "m5n.metal": ["c5n.metal", "m6i.metal"], - "c5n.metal": ["m5n.metal", "m6i.metal"], - "m6i.metal": ["m5n.metal", "c5n.metal"], + "m5n.metal": ["m6i.metal"], + "m6i.metal": ["m5n.metal"], }, "instances": [ - "c5n.metal", "m5n.metal", "m6i.metal", "m7i.metal-24xl", diff --git a/.buildkite/pipeline_cross.py b/.buildkite/pipeline_cross.py index e9a7be73891..f476fee76ad 100755 --- a/.buildkite/pipeline_cross.py +++ b/.buildkite/pipeline_cross.py @@ -19,7 +19,6 @@ per_instance.pop("instances") per_instance.pop("platforms") instances_x86_64 = [ - "c5n.metal", "m5n.metal", "m6i.metal", "m7i.metal-24xl", @@ -49,9 +48,8 @@ # allow-list of what instances can be restores on what other instances (in # addition to itself) supported = { - "c5n.metal": ["m5n.metal", "m6i.metal"], - "m5n.metal": ["c5n.metal", "m6i.metal"], - "m6i.metal": ["c5n.metal", "m5n.metal"], + "m5n.metal": ["m6i.metal"], + "m6i.metal": ["m5n.metal"], } # https://github.com/firecracker-microvm/firecracker/blob/main/docs/kernel-policy.md#experimental-snapshot-compatibility-across-kernel-versions @@ -82,7 +80,6 @@ continue pytest_keyword_for_instance = { - "c5n.metal": "-k 'not None'", "m5n.metal": "-k 'not None'", "m6i.metal": "-k 'not None'", "m6a.metal": "", diff --git a/.buildkite/pipeline_docker_popular.py b/.buildkite/pipeline_docker_popular.py new file mode 100755 index 00000000000..2bcbe2eed56 --- /dev/null +++ b/.buildkite/pipeline_docker_popular.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Buildkite pipeline for testing popular Docker containers +""" + +from common import BKPipeline, random_str + +pipeline = BKPipeline() + +ROOTFS_TAR = f"rootfs_$(uname -m)_{random_str(k=8)}.tar.gz" + +pipeline.build_group_per_arch( + ":ship: Rootfs build", + [ + "sudo yum install -y systemd-container", + "cd tools/test-popular-containers", + "sudo ./build_rootfs.sh", + f'tar czf "{ROOTFS_TAR}" *.ext4 *.id_rsa', + f'buildkite-agent artifact upload "{ROOTFS_TAR}"', + ], + depends_on_build=False, + set_key=ROOTFS_TAR, +) + +pipeline.build_group( + ":whale: Docker Popular Containers", + [ + "./tools/devtool download_ci_artifacts", + f'buildkite-agent artifact download "{ROOTFS_TAR}" .', + f'tar xzf "{ROOTFS_TAR}" -C tools/test-popular-containers', + './tools/devtool sh "cd ./tools/test-popular-containers; PYTHONPATH=../../tests ./test-docker-rootfs.py"', + ], + depends_on=ROOTFS_TAR, +) + +print(pipeline.to_json()) diff --git a/.buildkite/pipeline_release_qa.py b/.buildkite/pipeline_release_qa.py new file mode 100755 index 00000000000..7b25021812f --- /dev/null +++ b/.buildkite/pipeline_release_qa.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Buildkite pipeline for release QA +""" + +from common import BKPipeline + +pipeline = BKPipeline(with_build_step=False) + +# NOTE: we need to escape $ using $$ otherwise buildkite tries to replace it instead of the shell + +pipeline.add_step( + { + "label": "Download release", + "if": 'build.env("VERSION") != "dev"', + "command": [ + "aws s3 sync --no-sign-request s3://spec.ccfc.min/firecracker-ci/firecracker/$$VERSION release-$$VERSION", + 'buildkite-agent artifact upload "release-$$VERSION/**/*"', + ], + }, + depends_on_build=False, +) + +pipeline.build_group_per_arch( + ":building_construction: Make release", + # if is a keyword for python, so we need this workaround to expand it as a kwarg + **{"if": 'build.env("VERSION") == "dev"'}, + command=[ + "./tools/devtool -y make_release", + "RELEASE_DIR=$$(echo release-*dev-$$(uname -m))", + "RELEASE_SUFFIX=$${{RELEASE_DIR#release}}", + "OUT_DIR=release-$$VERSION/$$(uname -m)", + "mkdir -p $$OUT_DIR", + ( + "for f in $$RELEASE_DIR/*-$$(uname -m); do" + " mv $$f $$OUT_DIR/$$(basename $$f $$RELEASE_SUFFIX);" + " mv $$f.debug $$OUT_DIR/$$(basename $$f $$RELEASE_SUFFIX).debug;" + "done" + ), + 'buildkite-agent artifact upload "release-$$VERSION/**/*"', + ], + depends_on_build=False, +) + +# The devtool expects the examples to be in the same folder as the binaries to run some tests +# (for example, uffd handler tests). Build them and upload them in the same folder. +pipeline.build_group_per_arch( + ":hammer_and_wrench: Build examples", + command=[ + "CARGO_TARGET=$$(uname -m)-unknown-linux-musl", + "./tools/devtool -y sh cargo build --target $$CARGO_TARGET --release --examples", + "mkdir -p release-$$VERSION/$$(uname -m)/", + "cp -R build/cargo_target/$$CARGO_TARGET/release/examples release-$$VERSION/$$(uname -m)/", + 'buildkite-agent artifact upload "release-$$VERSION/**/*"', + ], + depends_on_build=False, +) + +pipeline.add_step("wait", depends_on_build=False) + +pipeline.add_step( + { + "label": ":pipeline: PR", + "command": ( + ".buildkite/pipeline_pr.py --binary-dir release-$$VERSION " + "| jq '(..|select(.priority? != null).priority) += 100' " + "| buildkite-agent pipeline upload" + ), + }, + depends_on_build=False, +) + +print(pipeline.to_json()) diff --git a/.mailmap b/.mailmap index 18c3c02beb1..b4c9ed51739 100644 --- a/.mailmap +++ b/.mailmap @@ -33,3 +33,5 @@ Muskaan Singla Nikita Zakirov Tomoya Iwata +Andrea Manzini +Colin Percival diff --git a/CHANGELOG.md b/CHANGELOG.md index e7eb43cf986..8af38184bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ and this project adheres to ### Fixed +- [#5418](https://github.com/firecracker-microvm/firecracker/pull/5418): Fixed + typo in Swagger definition of `MmdsConfig`, where the property `imds_compat` + was spelled as `imds_comat`. This caused auto-generated clients to create bad + requests. + ## [1.13.0] ### Added @@ -53,6 +58,12 @@ and this project adheres to guest's serial console. Not configuring it means Firecracker will continue to print serial output to stdout. Similarly to the logger, this configuration is not persisted across snapshots. +- [#5364](https://github.com/firecracker-microvm/firecracker/pull/5364): Added + PCI support in Firecracker. PCI support is optional. Users can enable it + passing the `--enable-pci` flag when launching the Firecracker process. When + Firecracker process is launched with PCI support, it will create all VirtIO + devices using a PCI VirtIO transport. If not enabled, Firecracker will use the + MMIO transport instead. ### Changed @@ -78,6 +89,11 @@ and this project adheres to ### Removed +- [#5411](https://github.com/firecracker-microvm/firecracker/pull/5411): Removed + official support for Intel Skylake instances. Firecracker will continue to + work on those instances, but we will no longer perform automated testing on + them. + ### Fixed - [#5222](https://github.com/firecracker-microvm/firecracker/pull/5222): Fixed diff --git a/CREDITS.md b/CREDITS.md index f8e68078dcc..0bbcbd8e809 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -21,6 +21,7 @@ Contributors to the Firecracker repository: - Aaron O'Mullan - Abhijeet Kasurde - acatangiu +- acsmyth <54330152+acsmyth@users.noreply.github.com> - Adam Jensen - Adam Leskis - Adrian Catangiu @@ -37,11 +38,12 @@ Contributors to the Firecracker repository: - Alexandru-Cezar Sardan - Alin Dima - Anatoli Babenia -- Andrea Manzini +- Andrea Manzini - Andreea Florescu - Andrei Casu-Pop - Andrei Cipu - Andrei Sandu +- Andrew Laucius - Andrew Yao - Andrii Radyk - andros21 @@ -76,11 +78,12 @@ Contributors to the Firecracker repository: - Christopher Diehl - Christos Katsakioris - cneira -- Colin Percival +- Colin Percival - Colton J. McCurdy - Constantin Musca - CuriousCorrelation - czybjtu +- Dakshin Devanand - Damien Stanton - Dan Horobeanu - Dan Lemmond @@ -98,12 +101,14 @@ Contributors to the Firecracker repository: - Eddie Cazares - Eduard Kyvenko - Egor Lazarchuk +- Emmanuel Ferdman - EvanJP - Felipe R. Monteiro - Filippo Sironi - Fraser Pringle - Gabe Jackson - Gabriel Ionescu +- Gabriel Kopper <41166074+gckopper@users.noreply.github.com> - Garrett Squire - George Pisaltu - George Siton @@ -112,6 +117,7 @@ Contributors to the Firecracker repository: - Greg Dunn - Gregory Brzeski - Grzegorz Uriasz +- Gudmundur Bjarni Olafsson - Gulshan Kumar - Gábor Lipták - hacker65536 @@ -120,6 +126,7 @@ Contributors to the Firecracker repository: - Hermes - Himanshu Neema - HQ01 +- huang-jl <1046678590@qq.com> - Iggy Jackson - ihciah - Ioana Chirca @@ -235,6 +242,7 @@ Contributors to the Firecracker repository: - Serban Iorga - shakram02 - Shen Jiale +- Sheng-Wei (Way) Chen - Shion Yamashita - singwm - sladynnunes diff --git a/Cargo.lock b/Cargo.lock index 7ec8aba673b..de60175ed79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,7 +201,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "cexpr", "clang-sys", "itertools 0.12.1", @@ -226,9 +226,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.3" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "bumpalo" @@ -260,10 +260,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.34" +version = "1.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -334,9 +335,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.45" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", "clap_derive", @@ -353,9 +354,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstream", "anstyle", @@ -365,9 +366,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck", "proc-macro2", @@ -581,7 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -594,6 +595,12 @@ dependencies = [ "vmm-sys-util", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "firecracker" version = "1.14.0-dev" @@ -629,7 +636,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b686b198dfaa4109ebd0443d2841bc521e4b4b2915f1d84b3bb50332a8cdc1ae" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "cfg-if", "log", "managed", @@ -822,9 +829,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" dependencies = [ "once_cell", "wasm-bindgen", @@ -847,7 +854,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e00243d27a20feb05cf001ae52ddc79831ac70c020f215ba1153ff9270b650a" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "kvm-bindings", "libc", "vmm-sys-util", @@ -878,7 +885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.2", + "windows-targets 0.52.6", ] [[package]] @@ -896,11 +903,17 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" dependencies = [ "serde", ] @@ -937,17 +950,17 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memfd" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix", + "rustix 1.0.8", ] [[package]] name = "micro_http" version = "0.1.0" -source = "git+https://github.com/firecracker-microvm/micro-http#98d85677ba603d16c40103c09059b54c38d71825" +source = "git+https://github.com/firecracker-microvm/micro-http#3248ceeae41461d034624b582d5d358cd6e6f89f" dependencies = [ "libc", "vmm-sys-util", @@ -965,7 +978,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "cfg-if", "libc", ] @@ -1097,7 +1110,7 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "lazy_static", "num-traits", "rand", @@ -1213,10 +1226,23 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.4", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -1411,7 +1437,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84e482e368cf7efa2c8b570f476e5b9fd9fd5e9b9219fc567832b05f13511091" dependencies = [ - "rustix", + "rustix 0.38.44", ] [[package]] @@ -1515,7 +1541,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b3a8a0cb358f7d1b7ee9b6784be122b6f51248a6d9e214d555beb9b44c72aea" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "cfg-if", "libc", "nix", @@ -1552,9 +1578,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.18.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom", "js-sys", @@ -1574,7 +1600,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a4dcad85a129d97d5d4b2f3c47a4affdeedd76bdcd02094bcb5d9b76cac2d05" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.9.4", "libc", "uuid", "vm-memory", @@ -1640,7 +1666,7 @@ dependencies = [ "aws-lc-rs", "base64", "bincode", - "bitflags 2.9.3", + "bitflags 2.9.4", "byteorder", "crc64", "criterion", @@ -1704,30 +1730,31 @@ dependencies = [ [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.4+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" dependencies = [ "bumpalo", "log", @@ -1739,9 +1766,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1749,9 +1776,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" dependencies = [ "proc-macro2", "quote", @@ -1762,9 +1789,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" dependencies = [ "unicode-ident", ] @@ -1778,7 +1805,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -1799,11 +1826,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -1965,28 +1992,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.3", -] +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", diff --git a/FAQ.md b/FAQ.md index 9456471df8c..8c47529661d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -129,7 +129,7 @@ Example of a kernel valid command line that enables the serial console (which goes in the `boot_args` field of the `/boot-source` Firecracker API resource): ```console -console=ttyS0 reboot=k panic=1 pci=off nomodule +console=ttyS0 reboot=k panic=1 nomodule ``` ### How can I configure multiple Ethernet devices through the kernel command line? diff --git a/README.md b/README.md index a03f098eb32..3e5eb984688 100644 --- a/README.md +++ b/README.md @@ -130,19 +130,18 @@ The **API endpoint** can be used to: We test all combinations of: -| Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | -| :------------- | :--------------- | :----------- | :----------- | -| c5n.metal | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | -| m5n.metal | al2023 linux_6.1 | | linux_6.1 | -| m6i.metal | | | | -| m7i.metal-24xl | | | | -| m7i.metal-48xl | | | | -| m6a.metal | | | | -| m7a.metal-48xl | | | | -| m6g.metal | | | | -| m7g.metal | | | | -| m8g.metal-24xl | | | | -| m8g.metal-48xl | | | | +| Instance | Host OS & Kernel | Guest Rootfs | Guest Kernel | +| :------------------------------------- | :--------------- | :----------- | :----------- | +| m5n.metal (Intel Cascade Lake) | al2 linux_5.10 | ubuntu 24.04 | linux_5.10 | +| m6i.metal (Intel Ice Lake) | al2023 linux_6.1 | | linux_6.1 | +| m7i.metal-24xl (Intel Sapphire Rapids) | | | | +| m7i.metal-48xl (Intel Sapphire Rapids) | | | | +| m6a.metal (AMD Milan) | | | | +| m7a.metal-48xl (AMD Genoa) | | | | +| m6g.metal (Graviton 2) | | | | +| m7g.metal (Graviton 3) | | | | +| m8g.metal-24xl (Graviton 4) | | | | +| m8g.metal-48xl (Graviton 4) | | | | ## Known issues and Limitations diff --git a/docs/RELEASE_POLICY.md b/docs/RELEASE_POLICY.md index ced8714d247..16b3a3b699a 100644 --- a/docs/RELEASE_POLICY.md +++ b/docs/RELEASE_POLICY.md @@ -90,6 +90,7 @@ v3.1 will be patched since were the last two Firecracker releases and less than | Release | Release Date | Latest Patch | Min. end of support | Official end of Support | | ------: | -----------: | -----------: | ------------------: | :------------------------------ | +| v1.13 | 2025-08-28 | v1.13.1 | 2026-02-28 | Supported | | v1.12 | 2025-05-07 | v1.12.1 | 2025-11-07 | Supported | | v1.11 | 2025-03-18 | v1.11.0 | 2025-09-18 | Supported | | v1.10 | 2024-11-07 | v1.10.1 | 2025-05-07 | 2025-05-07 (v1.12 released) | diff --git a/docs/device-api.md b/docs/device-api.md index f60e856aed7..01e470f1d64 100644 --- a/docs/device-api.md +++ b/docs/device-api.md @@ -14,22 +14,23 @@ BadRequest - HTTP response. ## API Endpoints -| Endpoint | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | virtio-rng | -| ------------------------- | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | :--------: | -| `boot-source` | O | O | O | O | O | O | O | -| `cpu-config` | O | O | O | O | O | O | O | -| `drives/{id}` | O | O | **R** | **R** | O | O | O | -| `logger` | O | O | O | O | O | O | O | -| `machine-config` | O | O | O | O | O | O | O | -| `metrics` | O | O | O | O | O | O | O | -| `mmds` | O | O | O | O | **R** | O | O | -| `mmds/config` | O | O | O | O | **R** | O | O | -| `network-interfaces/{id}` | O | O | O | O | **R** | O | O | -| `snapshot/create` | O | O | O | O | O | O | O | -| `snapshot/load` | O | O | O | O | O | O | O | -| `vm` | O | O | O | O | O | O | O | -| `vsock` | O | O | O | O | O | O | O | -| `entropy` | O | O | O | O | O | O | **R** | +| Endpoint | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | virtio-rng | virtio-mem | +| ------------------------- | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | :--------: | :--------: | +| `boot-source` | O | O | O | O | O | O | O | O | +| `cpu-config` | O | O | O | O | O | O | O | O | +| `drives/{id}` | O | O | **R** | **R** | O | O | O | O | +| `hotplug/memory` | O | O | O | O | O | O | O | **R** | +| `logger` | O | O | O | O | O | O | O | O | +| `machine-config` | O | O | O | O | O | O | O | O | +| `metrics` | O | O | O | O | O | O | O | O | +| `mmds` | O | O | O | O | **R** | O | O | O | +| `mmds/config` | O | O | O | O | **R** | O | O | O | +| `network-interfaces/{id}` | O | O | O | O | **R** | O | O | O | +| `snapshot/create` | O | O | O | O | O | O | O | O | +| `snapshot/load` | O | O | O | O | O | O | O | O | +| `vm` | O | O | O | O | O | O | O | O | +| `vsock` | O | O | O | O | O | O | O | O | +| `entropy` | O | O | O | O | O | O | **R** | O | ## Input Schema @@ -37,69 +38,72 @@ All input schema fields can be found in the [Swagger](https://swagger.io) specification: [firecracker.yaml](./../src/firecracker/swagger/firecracker.yaml). -| Schema | Property | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | virtio-rng | -| ------------------------- | ------------------ | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | :--------: | -| `BootSource` | boot_args | O | O | O | O | O | O | O | -| | initrd_path | O | O | O | O | O | O | O | -| | kernel_image_path | O | O | O | O | O | O | O | -| `CpuConfig` | cpuid_modifiers | O | O | O | O | O | O | O | -| | msr_modifiers | O | O | O | O | O | O | O | -| | reg_modifiers | O | O | O | O | O | O | O | -| `CpuTemplate` | enum | O | O | O | O | O | O | O | -| `CreateSnapshotParams` | mem_file_path | O | O | O | O | O | O | O | -| | snapshot_path | O | O | O | O | O | O | O | -| | snapshot_type | O | O | O | O | O | O | O | -| | version | O | O | O | O | O | O | O | -| `Drive` | drive_id \* | O | O | **R** | **R** | O | O | O | -| | is_read_only | O | O | **R** | O | O | O | O | -| | is_root_device \* | O | O | **R** | **R** | O | O | O | -| | partuuid \* | O | O | **R** | **R** | O | O | O | -| | path_on_host | O | O | **R** | O | O | O | O | -| | rate_limiter | O | O | **R** | O | O | O | O | -| | socket | O | O | O | **R** | O | O | O | -| `InstanceActionInfo` | action_type | O | O | O | O | O | O | O | -| `LoadSnapshotParams` | track_dirty_pages | O | O | O | O | O | O | O | -| | mem_file_path | O | O | O | O | O | O | O | -| | mem_backend | O | O | O | O | O | O | O | -| | snapshot_path | O | O | O | O | O | O | O | -| | resume_vm | O | O | O | O | O | O | O | -| `Logger` | level | O | O | O | O | O | O | O | -| | log_path | O | O | O | O | O | O | O | -| | show_level | O | O | O | O | O | O | O | -| | show_log_origin | O | O | O | O | O | O | O | -| `MachineConfiguration` | cpu_template | O | O | O | O | O | O | O | -| | smt | O | O | O | O | O | O | O | -| | mem_size_mib | O | O | O | O | O | O | O | -| | track_dirty_pages | O | O | O | O | O | O | O | -| | vcpu_count | O | O | O | O | O | O | O | -| `Metrics` | metrics_path | O | O | O | O | O | O | O | -| `MmdsConfig` | network_interfaces | O | O | O | O | **R** | O | O | -| | version | O | O | O | O | **R** | O | O | -| | ipv4_address | O | O | O | O | **R** | O | O | -| | imds_compat | O | O | O | O | O | O | O | -| `NetworkInterface` | guest_mac | O | O | O | O | **R** | O | O | -| | host_dev_name | O | O | O | O | **R** | O | O | -| | iface_id | O | O | O | O | **R** | O | O | -| | rx_rate_limiter | O | O | O | O | **R** | O | O | -| | tx_rate_limiter | O | O | O | O | **R** | O | O | -| `PartialDrive` | drive_id | O | O | **R** | O | O | O | O | -| | path_on_host | O | O | **R** | O | O | O | O | -| `PartialNetworkInterface` | iface_id | O | O | O | O | **R** | O | O | -| | rx_rate_limiter | O | O | O | O | **R** | O | O | -| | tx_rate_limiter | O | O | O | O | **R** | O | O | -| `RateLimiter` | bandwidth | O | O | O | O | **R** | O | O | -| | ops | O | O | **R** | O | O | O | O | -| `TokenBucket` \*\* | one_time_burst | O | O | **R** | O | O | O | O | -| | refill_time | O | O | **R** | O | O | O | O | -| | size | O | O | **R** | O | O | O | O | -| `TokenBucket` \*\* | one_time_burst | O | O | O | O | **R** | O | O | -| | refill_time | O | O | O | O | **R** | O | O | -| | size | O | O | O | O | **R** | O | O | -| `Vm` | state | O | O | O | O | O | O | O | -| `Vsock` | guest_cid | O | O | O | O | O | **R** | O | -| | uds_path | O | O | O | O | O | **R** | O | -| | vsock_id | O | O | O | O | O | **R** | O | -| `EntropyDevice` | rate_limiter | O | O | O | O | O | O | **R** | +| Schema | Property | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | virtio-rng | virtio-mem | +| ------------------------- | ------------------ | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | :--------: | :--------: | +| `BootSource` | boot_args | O | O | O | O | O | O | O | O | +| | initrd_path | O | O | O | O | O | O | O | O | +| | kernel_image_path | O | O | O | O | O | O | O | O | +| `CpuConfig` | cpuid_modifiers | O | O | O | O | O | O | O | O | +| | msr_modifiers | O | O | O | O | O | O | O | O | +| | reg_modifiers | O | O | O | O | O | O | O | O | +| `CpuTemplate` | enum | O | O | O | O | O | O | O | O | +| `CreateSnapshotParams` | mem_file_path | O | O | O | O | O | O | O | O | +| | snapshot_path | O | O | O | O | O | O | O | O | +| | snapshot_type | O | O | O | O | O | O | O | O | +| | version | O | O | O | O | O | O | O | O | +| `Drive` | drive_id \* | O | O | **R** | **R** | O | O | O | O | +| | is_read_only | O | O | **R** | O | O | O | O | O | +| | is_root_device \* | O | O | **R** | **R** | O | O | O | O | +| | partuuid \* | O | O | **R** | **R** | O | O | O | O | +| | path_on_host | O | O | **R** | O | O | O | O | O | +| | rate_limiter | O | O | **R** | O | O | O | O | O | +| | socket | O | O | O | **R** | O | O | O | O | +| `InstanceActionInfo` | action_type | O | O | O | O | O | O | O | O | +| `LoadSnapshotParams` | track_dirty_pages | O | O | O | O | O | O | O | O | +| | mem_file_path | O | O | O | O | O | O | O | O | +| | mem_backend | O | O | O | O | O | O | O | O | +| | snapshot_path | O | O | O | O | O | O | O | O | +| | resume_vm | O | O | O | O | O | O | O | O | +| `Logger` | level | O | O | O | O | O | O | O | O | +| | log_path | O | O | O | O | O | O | O | O | +| | show_level | O | O | O | O | O | O | O | O | +| | show_log_origin | O | O | O | O | O | O | O | O | +| `MachineConfiguration` | cpu_template | O | O | O | O | O | O | O | O | +| | smt | O | O | O | O | O | O | O | O | +| | mem_size_mib | O | O | O | O | O | O | O | O | +| | track_dirty_pages | O | O | O | O | O | O | O | O | +| | vcpu_count | O | O | O | O | O | O | O | O | +| `Metrics` | metrics_path | O | O | O | O | O | O | O | O | +| `MmdsConfig` | network_interfaces | O | O | O | O | **R** | O | O | O | +| | version | O | O | O | O | **R** | O | O | O | +| | ipv4_address | O | O | O | O | **R** | O | O | O | +| | imds_compat | O | O | O | O | O | O | O | O | +| `NetworkInterface` | guest_mac | O | O | O | O | **R** | O | O | O | +| | host_dev_name | O | O | O | O | **R** | O | O | O | +| | iface_id | O | O | O | O | **R** | O | O | O | +| | rx_rate_limiter | O | O | O | O | **R** | O | O | O | +| | tx_rate_limiter | O | O | O | O | **R** | O | O | O | +| `PartialDrive` | drive_id | O | O | **R** | O | O | O | O | O | +| | path_on_host | O | O | **R** | O | O | O | O | O | +| `PartialNetworkInterface` | iface_id | O | O | O | O | **R** | O | O | O | +| | rx_rate_limiter | O | O | O | O | **R** | O | O | O | +| | tx_rate_limiter | O | O | O | O | **R** | O | O | O | +| `RateLimiter` | bandwidth | O | O | O | O | **R** | O | O | O | +| | ops | O | O | **R** | O | O | O | O | O | +| `TokenBucket` \*\* | one_time_burst | O | O | **R** | O | O | O | O | O | +| | refill_time | O | O | **R** | O | O | O | O | O | +| | size | O | O | **R** | O | O | O | O | O | +| `TokenBucket` \*\* | one_time_burst | O | O | O | O | **R** | O | O | O | +| | refill_time | O | O | O | O | **R** | O | O | O | +| | size | O | O | O | O | **R** | O | O | O | +| `Vm` | state | O | O | O | O | O | O | O | O | +| `Vsock` | guest_cid | O | O | O | O | O | **R** | O | O | +| | uds_path | O | O | O | O | O | **R** | O | O | +| | vsock_id | O | O | O | O | O | **R** | O | O | +| `EntropyDevice` | rate_limiter | O | O | O | O | O | O | **R** | O | +| `MemoryHotplugConfig` | total_size_mib | O | O | O | O | O | O | O | **R** | +| | slot_size_mib | O | O | O | O | O | O | O | **R** | +| | block_size_mi | O | O | O | O | O | O | O | **R** | \* `Drive`'s `drive_id`, `is_root_device` and `partuuid` can be configured by either virtio-block or vhost-user-block devices. @@ -113,18 +117,24 @@ All output schema fields can be found in the [Swagger](https://swagger.io) specification: [firecracker.yaml](./../src/firecracker/swagger/firecracker.yaml). -| Schema | Property | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | -| ---------------------- | ----------------- | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | -| `Error` | fault_message | O | O | O | O | O | O | -| `InstanceInfo` | app_name | O | O | O | O | O | O | -| | id | O | O | O | O | O | O | -| | state | O | O | O | O | O | O | -| | vmm_version | O | O | O | O | O | O | -| `MachineConfiguration` | cpu_template | O | O | O | O | O | O | -| | smt | O | O | O | O | O | O | -| | mem_size_mib | O | O | O | O | O | O | -| | track_dirty_pages | O | O | O | O | O | O | -| | vcpu_count | O | O | O | O | O | O | +| Schema | Property | keyboard | serial console | virtio-block | vhost-user-block | virtio-net | virtio-vsock | virtio-mem | +| ---------------------- | ------------------ | :------: | :------------: | :----------: | :--------------: | :--------: | :----------: | :--------: | +| `Error` | fault_message | O | O | O | O | O | O | O | +| `InstanceInfo` | app_name | O | O | O | O | O | O | O | +| | id | O | O | O | O | O | O | O | +| | state | O | O | O | O | O | O | O | +| | vmm_version | O | O | O | O | O | O | O | +| `MachineConfiguration` | cpu_template | O | O | O | O | O | O | O | +| | smt | O | O | O | O | O | O | O | +| | mem_size_mib | O | O | O | O | O | O | O | +| | track_dirty_pages | O | O | O | O | O | O | O | +| | vcpu_count | O | O | O | O | O | O | O | +| | vmm_version | O | O | O | O | O | O | O | +| `MemoryHotplugStatus ` | total_size_mib | O | O | O | O | O | O | **R** | +| | slot_size_mib | O | O | O | O | O | O | **R** | +| | block_size_mib | O | O | O | O | O | O | **R** | +| | plugged_size_mib | O | O | O | O | O | O | **R** | +| | requested_size_mib | O | O | O | O | O | O | **R** | ## Instance Actions diff --git a/docs/getting-started.md b/docs/getting-started.md index f0b02c6e1b5..485d223a8ab 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -115,23 +115,29 @@ latest_ubuntu_key=$(curl "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecrac | sort -V | tail -1) ubuntu_version=$(basename $latest_ubuntu_key .squashfs | grep -oE '[0-9]+\.[0-9]+') -# Download a rootfs +# Download a rootfs from Firecracker CI wget -O ubuntu-$ubuntu_version.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/$latest_ubuntu_key" -# Create an ssh key for the rootfs +# The rootfs in our CI doesn't contain SSH keys to connect to the VM +# For the purpose of this demo, let's create one and patch it in the rootfs unsquashfs ubuntu-$ubuntu_version.squashfs.upstream ssh-keygen -f id_rsa -N "" cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys mv -v id_rsa ./ubuntu-$ubuntu_version.id_rsa # create ext4 filesystem image sudo chown -R root:root squashfs-root -truncate -s 400M ubuntu-$ubuntu_version.ext4 +truncate -s 1G ubuntu-$ubuntu_version.ext4 sudo mkfs.ext4 -d squashfs-root -F ubuntu-$ubuntu_version.ext4 # Verify everything was correctly set up and print versions -echo "Kernel: $(ls vmlinux-* | tail -1)" -echo "Rootfs: $(ls *.ext4 | tail -1)" -echo "SSH Key: $(ls *.id_rsa | tail -1)" +echo +echo "The following files were downloaded and set up:" +KERNEL=$(ls vmlinux-* | tail -1) +[ -f $KERNEL ] && echo "Kernel: $KERNEL" || echo "ERROR: Kernel $KERNEL does not exist" +ROOTFS=$(ls *.ext4 | tail -1) +e2fsck -fn $ROOTFS &>/dev/null && echo "Rootfs: $ROOTFS" || echo "ERROR: $ROOTFS is not a valid ext4 fs" +KEY_NAME=$(ls *.id_rsa | tail -1) +[ -f $KEY_NAME ] && echo "SSH Key: $KEY_NAME" || echo "ERROR: Key $KEY_NAME does not exist" ``` ### Getting a Firecracker Binary @@ -194,9 +200,16 @@ API_SOCKET="/tmp/firecracker.socket" sudo rm -f $API_SOCKET # Run firecracker -sudo ./firecracker --api-sock "${API_SOCKET}" +sudo ./firecracker --api-sock "${API_SOCKET}" --enable-pci ``` +The `--enable-pci` flag instructs Firecracker to create all VirtIO devices using +a PCI VirtIO transport. This flag is optional. If not passed, Firecracker will +create devices using the legacy MMIO transport. We suggest that users enable the +PCI transport, as it yields higher throughput and lower latency for VirtIO +devices. For more information regarding guest kernel requirements for using PCI +look at our [kernel policy documentation](./kernel-policy.md). + In a new terminal (do not close the 1st one): ```bash @@ -240,7 +253,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \ "http://localhost/logger" KERNEL="./$(ls vmlinux* | tail -1)" -KERNEL_BOOT_ARGS="console=ttyS0 reboot=k panic=1 pci=off" +KERNEL_BOOT_ARGS="console=ttyS0 reboot=k panic=1" ARCH=$(uname -m) diff --git a/docs/kernel-policy.md b/docs/kernel-policy.md index 86823459d44..9387244118b 100644 --- a/docs/kernel-policy.md +++ b/docs/kernel-policy.md @@ -69,6 +69,15 @@ The configuration items that may be relevant for Firecracker are: - use CPU RNG instructions (if present) to initialize RNG. Available for >= 5.10 - ACPI support - `CONFIG_ACPI` and `CONFIG_PCI` +- PCI support: + - `CONFIG_BLK_MQ_PCI` + - `CONFIG_PCI` + - `CONFIG_PCI_MMCONFIG` + - `CONFIG_PCI_MSI` + - `CONFIG_PCIEPORTBUS` + - `CONFIG_VIRTIO_PCI` + - `CONFIG_PCI_HOST_COMMON` + - `CONFIG_PCI_HOST_GENERIC` There are also guest config options which are dependant on the platform on which Firecracker is run: @@ -142,6 +151,63 @@ following configurations: - Only legacy mechanisms - Both ACPI and legacy mechanisms +##### Booting with PCI: + +Firecracker supports booting guest microVMs with PCI support. This option is +enabled using the `--enable-pci` flag when launching the Firecracker process. +With PCI enabled, Firecracker will create all VirtIO devices using a PCI VirtIO +transport. The PCI transport typically achieves higher throughput and lower +latency for VirtIO devices. No further, per device, configuration is needed to +enable the PCI transport. + +PCI support is optional; if it is not enabled Firecracker will create VirtIO +devices using the MMIO transport. + +For Firecracker microVMs to boot properly with PCI support, use a guest kernel +built with PCI support. See the relevant Kconfig flags in our list of +[relevant Kconfig options](#guest-kernel-configuration-items): + +> [!IMPORTANT] +> +> Make sure that the kernel command line **does NOT** include the `pci=off` +> slug, which disables PCI support during boot time within the guest. When PCI +> is disabled, Firecracker will add this slug in the command line to instruct +> the guest kernel to skip useless PCI checks. For more info, look into the +> section for [Kernel command line parameters](#kernel-command-line-parameters). + +> [!NOTE] +> +> On x86_64 systems, `CONFIG_PCI` Kconfig option is needed even when booting +> microVMs without PCI support in case users want to use ACPI to boot. See +> [here](#booting-with-acpi-x86_64-only) for more info. + +## Kernel command line parameters + +By default, Firecracker will boot a guest microVM passing the following command +line parameters to the kernel: + +`reboot=k panic=1 nomodule 8250.nr_uarts=0 i8042.noaux i8042.nomux i8042.dumbkbd swiotlb=noforce`. + +- `reboot=k` shut down the guest on reboot, instead of rebooting +- `panic=1` on panic, reboot after 1 second +- `nomodule` disable loadable kernel module support +- `8250.nr_uarts=0` disable 8250 serial interface +- `i8042.noaux` do not probe the i8042 controller for an attached mouse (save + boot time) +- `i8042.nomux` do not probe i8042 for a multiplexing controller (save boot + time) +- `i8042.dumbkbd` do not attempt to control kbd state via the i8042 (save boot + time) +- `swiotlb=noforce` disable software bounce buffers (SWIOTLB) + +When running without [PCI support](#booting-with-pci), Firecracker will also +append `pci=off` to the above list. This option instructs the guest kernel to +avoid PCI probing. + +Users can provide their own command line parameters through the `boot_args` +field of the `/boot-source` +[Firecracker API](../src/firecracker/swagger/firecracker.yaml). + ## Caveats - [Snapshot compatibility across kernel versions](snapshotting/snapshot-support.md#snapshot-compatibility-across-kernel-versions) diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 9f8a443179d..6e1ac4d4c35 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -625,10 +625,11 @@ the compatibility table reported below: | .metal instance type | taken on host kernel | restored on host kernel | | -------------------- | -------------------- | ----------------------- | -| {c5n,m5n,m6i,m6a} | 5.10 | 6.1 | +| {m5n,m6i,m6a} | 5.10 | 6.1 | -For example, a snapshot taken on a m6i.metal host running a 5.10 host kernel can -be restored on a different m6i.metal host running a 6.1 host kernel (but not -vice versa), but could not be restored on a c5n.metal host. +For example, a snapshot taken on a m6i.metal host (Intel Ice Lake) running a +5.10 host kernel can be restored on a different m6i.metal host running a 6.1 +host kernel (but not vice versa), but could not be restored on a m5n.metal host +(Intel Cascade Lake). [man mincore]: https://man7.org/linux/man-pages/man2/mincore.2.html diff --git a/resources/guest_configs/ci.config b/resources/guest_configs/ci.config index 166ab94db3f..02ae7bfacf1 100644 --- a/resources/guest_configs/ci.config +++ b/resources/guest_configs/ci.config @@ -11,4 +11,8 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_GSCPS2=y CONFIG_KEYBOARD_ATKBD=y -CONFIG_INPUT_KEYBOARD=y \ No newline at end of file +CONFIG_INPUT_KEYBOARD=y + +# virtio-mem support +CONFIG_STRICT_DEVMEM=y +CONFIG_VIRTIO_MEM=y \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e12c5060d79..42b483c8095 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -11,7 +11,7 @@ # allowlisted using a toolchain that requires it, causing the A/B-test to # always fail. [toolchain] -channel = "1.87.0" +channel = "1.89.0" targets = ["x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl"] profile = "minimal" diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml index e401cf810aa..0848a5616f1 100644 --- a/src/acpi-tables/Cargo.toml +++ b/src/acpi-tables/Cargo.toml @@ -16,7 +16,7 @@ bench = false displaydoc = "0.2.5" thiserror = "2.0.16" vm-memory = { version = "0.16.2", features = ["backend-mmap", "backend-bitmap"] } -zerocopy = { version = "0.8.26", features = ["derive"] } +zerocopy = { version = "0.8.27", features = ["derive"] } [lints] workspace = true diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml index c9efb2226c5..59ea7b2e26d 100644 --- a/src/clippy-tracing/Cargo.toml +++ b/src/clippy-tracing/Cargo.toml @@ -10,7 +10,7 @@ name = "clippy-tracing" bench = false [dependencies] -clap = { version = "4.5.45", features = ["derive"] } +clap = { version = "4.5.47", features = ["derive"] } itertools = "0.14.0" proc-macro2 = { version = "1.0.101", features = ["span-locations"] } quote = "1.0.40" @@ -18,7 +18,7 @@ syn = { version = "2.0.106", features = ["full", "extra-traits", "visit", "visit walkdir = "2.5.0" [dev-dependencies] -uuid = { version = "1.18.0", features = ["v4"] } +uuid = { version = "1.18.1", features = ["v4"] } [lints] workspace = true diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml index 5168663d545..2db7bfe15bd 100644 --- a/src/cpu-template-helper/Cargo.toml +++ b/src/cpu-template-helper/Cargo.toml @@ -13,7 +13,7 @@ bench = false tracing = ["log-instrument", "vmm/tracing"] [dependencies] -clap = { version = "4.5.45", features = ["derive", "string"] } +clap = { version = "4.5.47", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.175" log-instrument = { path = "../log-instrument", optional = true } diff --git a/src/firecracker/src/api_server/mod.rs b/src/firecracker/src/api_server/mod.rs index 71d1856b0d5..60daaa26639 100644 --- a/src/firecracker/src/api_server/mod.rs +++ b/src/firecracker/src/api_server/mod.rs @@ -174,12 +174,12 @@ impl ApiServer { let vmm_outcome = *(self.vmm_response_receiver.recv().expect("VMM disconnected")); let response = ParsedRequest::convert_to_response(&vmm_outcome); - if vmm_outcome.is_ok() { - if let Some((metric, action)) = metric_with_action { - let elapsed_time_us = - update_metric_with_elapsed_time(metric, request_processing_start_us); - info!("'{}' API request took {} us.", action, elapsed_time_us); - } + if vmm_outcome.is_ok() + && let Some((metric, action)) = metric_with_action + { + let elapsed_time_us = + update_metric_with_elapsed_time(metric, request_processing_start_us); + info!("'{}' API request took {} us.", action, elapsed_time_us); } response } diff --git a/src/firecracker/src/api_server/parsed_request.rs b/src/firecracker/src/api_server/parsed_request.rs index 216e7c7fcf2..287742ede41 100644 --- a/src/firecracker/src/api_server/parsed_request.rs +++ b/src/firecracker/src/api_server/parsed_request.rs @@ -27,6 +27,9 @@ use super::request::net::{parse_patch_net, parse_put_net}; use super::request::snapshot::{parse_patch_vm_state, parse_put_snapshot}; use super::request::version::parse_get_version; use super::request::vsock::parse_put_vsock; +use crate::api_server::request::hotplug::memory::{ + parse_get_memory_hotplug, parse_put_memory_hotplug, +}; use crate::api_server::request::serial::parse_put_serial; #[derive(Debug)] @@ -84,6 +87,9 @@ impl TryFrom<&Request> for ParsedRequest { } (Method::Get, "machine-config", None) => parse_get_machine_config(), (Method::Get, "mmds", None) => parse_get_mmds(), + (Method::Get, "hotplug", None) if path_tokens.next() == Some("memory") => { + parse_get_memory_hotplug() + } (Method::Get, _, Some(_)) => method_to_error(Method::Get), (Method::Put, "actions", Some(body)) => parse_put_actions(body), (Method::Put, "balloon", Some(body)) => parse_put_balloon(body), @@ -101,6 +107,9 @@ impl TryFrom<&Request> for ParsedRequest { (Method::Put, "snapshot", Some(body)) => parse_put_snapshot(body, path_tokens.next()), (Method::Put, "vsock", Some(body)) => parse_put_vsock(body), (Method::Put, "entropy", Some(body)) => parse_put_entropy(body), + (Method::Put, "hotplug", Some(body)) if path_tokens.next() == Some("memory") => { + parse_put_memory_hotplug(body) + } (Method::Put, _, None) => method_to_error(Method::Put), (Method::Patch, "balloon", Some(body)) => parse_patch_balloon(body, path_tokens.next()), (Method::Patch, "drives", Some(body)) => parse_patch_drive(body, path_tokens.next()), @@ -173,6 +182,7 @@ impl ParsedRequest { Self::success_response_with_data(balloon_config) } VmmData::BalloonStats(stats) => Self::success_response_with_data(stats), + VmmData::VirtioMemStatus(data) => Self::success_response_with_data(data), VmmData::InstanceInformation(info) => Self::success_response_with_data(info), VmmData::VmmVersion(version) => Self::success_response_with_data( &serde_json::json!({ "firecracker_version": version.as_str() }), @@ -557,6 +567,9 @@ pub mod tests { VmmData::BalloonStats(stats) => { http_response(&serde_json::to_string(stats).unwrap(), 200) } + VmmData::VirtioMemStatus(data) => { + http_response(&serde_json::to_string(data).unwrap(), 200) + } VmmData::Empty => http_response("", 204), VmmData::FullVmConfig(cfg) => { http_response(&serde_json::to_string(cfg).unwrap(), 200) diff --git a/src/firecracker/src/api_server/request/hotplug/memory.rs b/src/firecracker/src/api_server/request/hotplug/memory.rs new file mode 100644 index 00000000000..4bdeec73a6d --- /dev/null +++ b/src/firecracker/src/api_server/request/hotplug/memory.rs @@ -0,0 +1,83 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use micro_http::Body; +use vmm::logger::{IncMetric, METRICS}; +use vmm::rpc_interface::VmmAction; +use vmm::vmm_config::memory_hotplug::MemoryHotplugConfig; + +use crate::api_server::parsed_request::{ParsedRequest, RequestError}; + +pub(crate) fn parse_put_memory_hotplug(body: &Body) -> Result { + METRICS.put_api_requests.hotplug_memory_count.inc(); + let config = serde_json::from_slice::(body.raw()).inspect_err(|_| { + METRICS.put_api_requests.hotplug_memory_fails.inc(); + })?; + Ok(ParsedRequest::new_sync(VmmAction::SetMemoryHotplugDevice( + config, + ))) +} + +pub(crate) fn parse_get_memory_hotplug() -> Result { + METRICS.get_api_requests.hotplug_memory_count.inc(); + Ok(ParsedRequest::new_sync(VmmAction::GetMemoryHotplugStatus)) +} + +#[cfg(test)] +mod tests { + use vmm::devices::virtio::mem::{ + VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB, VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB, + }; + + use super::*; + use crate::api_server::parsed_request::tests::vmm_action_from_request; + + #[test] + fn test_parse_put_memory_hotplug_request() { + parse_put_memory_hotplug(&Body::new("invalid_payload")).unwrap_err(); + + // PUT with invalid fields. + let body = r#"{ + "total_size_mib": "bar" + }"#; + parse_put_memory_hotplug(&Body::new(body)).unwrap_err(); + + // PUT with valid input fields with defaults. + let body = r#"{ + "total_size_mib": 2048 + }"#; + let expected_config = MemoryHotplugConfig { + total_size_mib: 2048, + block_size_mib: VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB, + slot_size_mib: VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB, + }; + assert_eq!( + vmm_action_from_request(parse_put_memory_hotplug(&Body::new(body)).unwrap()), + VmmAction::SetMemoryHotplugDevice(expected_config) + ); + + // PUT with valid input fields. + let body = r#"{ + "total_size_mib": 2048, + "block_size_mib": 64, + "slot_size_mib": 64 + }"#; + let expected_config = MemoryHotplugConfig { + total_size_mib: 2048, + block_size_mib: 64, + slot_size_mib: 64, + }; + assert_eq!( + vmm_action_from_request(parse_put_memory_hotplug(&Body::new(body)).unwrap()), + VmmAction::SetMemoryHotplugDevice(expected_config) + ); + } + + #[test] + fn test_parse_parse_get_memory_hotplug_request() { + assert_eq!( + vmm_action_from_request(parse_get_memory_hotplug().unwrap()), + VmmAction::GetMemoryHotplugStatus + ); + } +} diff --git a/src/firecracker/src/api_server/request/hotplug/mod.rs b/src/firecracker/src/api_server/request/hotplug/mod.rs new file mode 100644 index 00000000000..50b97ea2b80 --- /dev/null +++ b/src/firecracker/src/api_server/request/hotplug/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +pub mod memory; diff --git a/src/firecracker/src/api_server/request/mod.rs b/src/firecracker/src/api_server/request/mod.rs index a406842d0a6..d9f15828d3e 100644 --- a/src/firecracker/src/api_server/request/mod.rs +++ b/src/firecracker/src/api_server/request/mod.rs @@ -7,6 +7,7 @@ pub mod boot_source; pub mod cpu_configuration; pub mod drive; pub mod entropy; +pub mod hotplug; pub mod instance_info; pub mod logger; pub mod machine_configuration; diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index 3b1a1869239..c5011a79fd7 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -528,6 +528,43 @@ paths: schema: $ref: "#/definitions/Error" + /hotplug/memory: + put: + summary: Configures the hotpluggable memory + operationId: putMemoryHotplug + description: + Configure the hotpluggable memory, which is a virtio-mem device, with an associated memory area + that can be hot(un)plugged in the guest on demand using the PATCH API. + parameters: + - name: body + in: body + description: Hotpluggable memory configuration + required: true + schema: + $ref: "#/definitions/MemoryHotplugConfig" + responses: + 204: + description: Hotpluggable memory configured + default: + description: Internal server error + schema: + $ref: "#/definitions/Error" + get: + summary: Retrieves the status of the hotpluggable memory + operationId: getMemoryHotplug + description: + Reuturn the status of the hotpluggable memory. This can be used to follow the progress of the guest + after a PATCH API. + responses: + 200: + description: OK + schema: + $ref: "#/definitions/MemoryHotplugStatus" + default: + description: Internal server error + schema: + $ref: "#/definitions/Error" + /network-interfaces/{iface_id}: put: summary: Creates a network interface. Pre-boot only. @@ -596,7 +633,7 @@ paths: parameters: - name: body in: body - description: The configuration used for creating a snaphot. + description: The configuration used for creating a snapshot. required: true schema: $ref: "#/definitions/SnapshotCreateParams" @@ -623,7 +660,7 @@ paths: parameters: - name: body in: body - description: The configuration used for loading a snaphot. + description: The configuration used for loading a snapshot. required: true schema: $ref: "#/definitions/SnapshotLoadParams" @@ -1146,10 +1183,10 @@ definitions: format: "169.254.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]).([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" default: "169.254.169.254" description: A valid IPv4 link-local address. - imds_comat: + imds_compat: type: boolean description: - MMDS operates compatibly with EC2 IMDS (i.e. reponds "text/plain" + MMDS operates compatibly with EC2 IMDS (i.e. responds "text/plain" content regardless of Accept header in requests). default: false @@ -1364,6 +1401,48 @@ definitions: type: string description: Path to a file or named pipe on the host to which serial output should be written. + MemoryHotplugConfig: + type: object + description: + The configuration of the hotpluggable memory device (virtio-mem) + properties: + total_size_mib: + type: integer + description: Total size of the hotpluggable memory in MiB. + slot_size_mib: + type: integer + default: 128 + minimum: 128 + description: Slot size for the hotpluggable memory in MiB. This will determine the granularity of + hot-plug memory from the host. Refer to the device documentation on how to tune this value. + block_size_mib: + type: integer + default: 2 + minimum: 2 + description: (Logical) Block size for the hotpluggable memory in MiB. This will determine the logical + granularity of hot-plug memory for the guest. Refer to the device documentation on how to tune this value. + + MemoryHotplugStatus: + type: object + description: + The status of the hotpluggable memory device (virtio-mem) + properties: + total_size_mib: + type: integer + description: Total size of the hotpluggable memory in MiB. + slot_size_mib: + type: integer + description: Slot size for the hotpluggable memory in MiB. + block_size_mib: + type: integer + description: (Logical) Block size for the hotpluggable memory in MiB. + plugged_size_mib: + type: integer + description: Plugged size for the hotpluggable memory in MiB. + requested_size_mib: + type: integer + description: Requested size for the hotpluggable memory in MiB. + FirecrackerVersion: type: object description: diff --git a/src/log-instrument/Cargo.toml b/src/log-instrument/Cargo.toml index 3d60231ad89..f1c6a27dbed 100644 --- a/src/log-instrument/Cargo.toml +++ b/src/log-instrument/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" bench = false [dependencies] -log = "0.4.27" +log = "0.4.28" log-instrument-macros = { path = "../log-instrument-macros" } [dev-dependencies] diff --git a/src/pci/Cargo.toml b/src/pci/Cargo.toml index f803fde87b1..27a1e9918c7 100644 --- a/src/pci/Cargo.toml +++ b/src/pci/Cargo.toml @@ -15,7 +15,7 @@ default = [] byteorder = "1.5.0" displaydoc = "0.2.5" libc = "0.2.175" -log = "0.4.27" +log = "0.4.28" serde = { version = "1.0.219", features = ["derive"] } thiserror = "2.0.16" vm-allocator = "0.1.3" diff --git a/src/pci/src/bus.rs b/src/pci/src/bus.rs index 01c9b1f1933..12188ee7ba5 100644 --- a/src/pci/src/bus.rs +++ b/src/pci/src/bus.rs @@ -161,6 +161,9 @@ impl PciConfigIo { return 0xffff_ffff; } + // NOTE: Potential contention among vCPU threads on this lock. This should not + // be a problem currently, since we mainly access this when we are setting up devices. + // We might want to do some profiling to ensure this does not become a bottleneck. self.pci_bus .as_ref() .lock() @@ -195,6 +198,9 @@ impl PciConfigIo { return None; } + // NOTE: Potential contention among vCPU threads on this lock. This should not + // be a problem currently, since we mainly access this when we are setting up devices. + // We might want to do some profiling to ensure this does not become a bottleneck. let pci_bus = self.pci_bus.as_ref().lock().unwrap(); if let Some(d) = pci_bus.devices.get(&(device as u32)) { let mut device = d.lock().unwrap(); diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml index e51094b9261..38f21607576 100644 --- a/src/seccompiler/Cargo.toml +++ b/src/seccompiler/Cargo.toml @@ -17,13 +17,13 @@ bench = false [dependencies] bincode = { version = "2.0.1", features = ["serde"] } -clap = { version = "4.5.45", features = ["derive", "string"] } +clap = { version = "4.5.47", features = ["derive", "string"] } displaydoc = "0.2.5" libc = "0.2.175" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.143" thiserror = "2.0.16" -zerocopy = { version = "0.8.26" } +zerocopy = { version = "0.8.27" } [lints] workspace = true diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml index 84bce49a413..77c256ec20b 100644 --- a/src/snapshot-editor/Cargo.toml +++ b/src/snapshot-editor/Cargo.toml @@ -13,7 +13,7 @@ bench = false tracing = ["log-instrument", "fc_utils/tracing", "vmm/tracing"] [dependencies] -clap = { version = "4.5.45", features = ["derive", "string"] } +clap = { version = "4.5.47", features = ["derive", "string"] } displaydoc = "0.2.5" fc_utils = { package = "utils", path = "../utils" } diff --git a/src/utils/src/arg_parser.rs b/src/utils/src/arg_parser.rs index e76d38b7609..24992594137 100644 --- a/src/utils/src/arg_parser.rs +++ b/src/utils/src/arg_parser.rs @@ -77,7 +77,7 @@ impl<'a> ArgParser<'a> { } /// Return a reference to `arguments` field. - pub fn arguments(&self) -> &Arguments { + pub fn arguments(&self) -> &Arguments<'_> { &self.arguments } @@ -368,10 +368,10 @@ impl<'a> Arguments<'a> { if argument.user_value.is_some() { // For the arguments that require a specific argument to be also present in the list // of arguments provided by user, search for that argument. - if let Some(arg_name) = argument.requires { - if !args.contains(&(format!("--{}", arg_name))) { - return Err(UtilsArgParserError::MissingArgument(arg_name.to_string())); - } + if let Some(arg_name) = argument.requires + && !args.contains(&(format!("--{}", arg_name))) + { + return Err(UtilsArgParserError::MissingArgument(arg_name.to_string())); } // Check the user-provided list for potential forbidden arguments. for arg_name in argument.forbids.iter() { diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml index 2588c52c1be..6aada3d9026 100644 --- a/src/vmm/Cargo.toml +++ b/src/vmm/Cargo.toml @@ -22,7 +22,7 @@ arrayvec = { version = "0.7.6", optional = true } aws-lc-rs = { version = "1.13.3", features = ["bindgen"] } base64 = "0.22.1" bincode = { version = "2.0.1", features = ["serde"] } -bitflags = "2.9.3" +bitflags = "2.9.4" byteorder = "1.5.0" crc64 = "2.0.0" derive_more = { version = "2.0.1", default-features = false, features = [ @@ -37,9 +37,9 @@ kvm-bindings = { version = "0.13.0", features = ["fam-wrappers", "serde"] } kvm-ioctls = "0.23.0" libc = "0.2.175" linux-loader = "0.13.0" -log = { version = "0.4.27", features = ["std", "serde"] } +log = { version = "0.4.28", features = ["std", "serde"] } log-instrument = { path = "../log-instrument", optional = true } -memfd = "0.6.3" +memfd = "0.6.5" micro_http = { git = "https://github.com/firecracker-microvm/micro-http" } pci = { path = "../pci" } semver = { version = "1.0.26", features = ["serde"] } @@ -50,7 +50,7 @@ thiserror = "2.0.16" timerfd = "1.5.0" userfaultfd = "0.9.0" utils = { path = "../utils" } -uuid = "1.18.0" +uuid = "1.18.1" vhost = { version = "0.14.0", features = ["vhost-user-frontend"] } vm-allocator = { version = "0.1.3", features = ["serde"] } vm-device = { path = "../vm-device" } @@ -60,7 +60,7 @@ vm-memory = { version = "0.16.2", features = [ ] } vm-superio = "0.8.0" vmm-sys-util = { version = "0.14.0", features = ["with-serde"] } -zerocopy = { version = "0.8.26" } +zerocopy = { version = "0.8.27" } [target.'cfg(target_arch = "aarch64")'.dependencies] vm-fdt = "0.3.0" diff --git a/src/vmm/src/arch/aarch64/mod.rs b/src/vmm/src/arch/aarch64/mod.rs index a599db5dea7..74c5204af0e 100644 --- a/src/vmm/src/arch/aarch64/mod.rs +++ b/src/vmm/src/arch/aarch64/mod.rs @@ -169,10 +169,10 @@ fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 { // we return the start of the DRAM so that // we allow the code to try and load the FDT. - if let Some(addr) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) { - if mem.address_in_range(addr) { - return addr.raw_value(); - } + if let Some(addr) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) + && mem.address_in_range(addr) + { + return addr.raw_value(); } layout::DRAM_MEM_START diff --git a/src/vmm/src/arch/aarch64/regs.rs b/src/vmm/src/arch/aarch64/regs.rs index 74a5eaf2be3..7a24337e5c0 100644 --- a/src/vmm/src/arch/aarch64/regs.rs +++ b/src/vmm/src/arch/aarch64/regs.rs @@ -243,7 +243,7 @@ impl Aarch64RegisterVec { } /// Returns an iterator over stored registers. - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator> { Aarch64RegisterVecIterator { index: 0, offset: 0, @@ -253,7 +253,7 @@ impl Aarch64RegisterVec { } /// Returns an iterator over stored registers that allows register modifications. - pub fn iter_mut(&mut self) -> impl Iterator { + pub fn iter_mut(&mut self) -> impl Iterator> { Aarch64RegisterVecIteratorMut { index: 0, offset: 0, diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 6d33ce461b9..8113d83a2c3 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -22,11 +22,11 @@ pub use aarch64::vm::{ArchVm, ArchVmError, VmState}; pub use aarch64::{ ConfigurationError, arch_memory_regions, configure_system_for_boot, get_kernel_start, initrd_load_addr, layout::BOOT_DEVICE_MEM_START, layout::CMDLINE_MAX_SIZE, - layout::GSI_LEGACY_END, layout::GSI_LEGACY_NUM, layout::GSI_LEGACY_START, layout::GSI_MSI_END, - layout::GSI_MSI_NUM, layout::GSI_MSI_START, layout::MEM_32BIT_DEVICES_SIZE, - layout::MEM_32BIT_DEVICES_START, layout::MEM_64BIT_DEVICES_SIZE, - layout::MEM_64BIT_DEVICES_START, layout::MMIO32_MEM_SIZE, layout::MMIO32_MEM_START, - layout::PCI_MMCONFIG_SIZE, layout::PCI_MMCONFIG_START, + layout::FIRST_ADDR_PAST_64BITS_MMIO, layout::GSI_LEGACY_END, layout::GSI_LEGACY_NUM, + layout::GSI_LEGACY_START, layout::GSI_MSI_END, layout::GSI_MSI_NUM, layout::GSI_MSI_START, + layout::MEM_32BIT_DEVICES_SIZE, layout::MEM_32BIT_DEVICES_START, + layout::MEM_64BIT_DEVICES_SIZE, layout::MEM_64BIT_DEVICES_START, layout::MMIO32_MEM_SIZE, + layout::MMIO32_MEM_START, layout::PCI_MMCONFIG_SIZE, layout::PCI_MMCONFIG_START, layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT, layout::RTC_MEM_START, layout::SERIAL_MEM_START, layout::SPI_START, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, load_kernel, }; @@ -46,9 +46,9 @@ pub use x86_64::vm::{ArchVm, ArchVmError, VmState}; pub use crate::arch::x86_64::{ ConfigurationError, arch_memory_regions, configure_system_for_boot, get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::BOOT_DEVICE_MEM_START, layout::CMDLINE_MAX_SIZE, - layout::GSI_LEGACY_END, layout::GSI_LEGACY_NUM, layout::GSI_LEGACY_START, layout::GSI_MSI_END, - layout::GSI_MSI_NUM, layout::GSI_MSI_START, layout::IOAPIC_ADDR, - layout::MEM_32BIT_DEVICES_SIZE, layout::MEM_32BIT_DEVICES_START, + layout::FIRST_ADDR_PAST_64BITS_MMIO, layout::GSI_LEGACY_END, layout::GSI_LEGACY_NUM, + layout::GSI_LEGACY_START, layout::GSI_MSI_END, layout::GSI_MSI_NUM, layout::GSI_MSI_START, + layout::IOAPIC_ADDR, layout::MEM_32BIT_DEVICES_SIZE, layout::MEM_32BIT_DEVICES_START, layout::MEM_64BIT_DEVICES_SIZE, layout::MEM_64BIT_DEVICES_START, layout::MMIO32_MEM_SIZE, layout::MMIO32_MEM_START, layout::PCI_MMCONFIG_SIZE, layout::PCI_MMCONFIG_START, layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, diff --git a/src/vmm/src/arch/x86_64/mod.rs b/src/vmm/src/arch/x86_64/mod.rs index 1822abb9009..b18267c6a1e 100644 --- a/src/vmm/src/arch/x86_64/mod.rs +++ b/src/vmm/src/arch/x86_64/mod.rs @@ -132,19 +132,19 @@ pub fn arch_memory_regions(size: usize) -> Vec<(GuestAddress, usize)> { dram_size, u64_to_usize(MMIO32_MEM_START), u64_to_usize(MMIO32_MEM_SIZE), - ) { - if let Some((start_past_64bit_gap, remaining_past_64bit_gap)) = arch_memory_regions_with_gap( + ) && let Some((start_past_64bit_gap, remaining_past_64bit_gap)) = + arch_memory_regions_with_gap( &mut regions, start_past_32bit_gap, remaining_past_32bit_gap, u64_to_usize(MMIO64_MEM_START), u64_to_usize(MMIO64_MEM_SIZE), - ) { - regions.push(( - GuestAddress(start_past_64bit_gap as u64), - remaining_past_64bit_gap, - )); - } + ) + { + regions.push(( + GuestAddress(start_past_64bit_gap as u64), + remaining_past_64bit_gap, + )); } regions diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index dbfe4232381..ed972c804c0 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -32,6 +32,7 @@ use crate::device_manager::{ use crate::devices::acpi::vmgenid::VmGenIdError; use crate::devices::virtio::balloon::Balloon; use crate::devices::virtio::block::device::Block; +use crate::devices::virtio::mem::VirtioMem; use crate::devices::virtio::net::Net; use crate::devices::virtio::rng::Entropy; use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend}; @@ -45,6 +46,7 @@ use crate::seccomp::BpfThreadMap; use crate::snapshot::Persist; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::MachineConfigError; +use crate::vmm_config::memory_hotplug::MemoryHotplugConfig; use crate::vstate::kvm::{Kvm, KvmError}; use crate::vstate::memory::GuestRegionMmap; #[cfg(target_arch = "aarch64")] @@ -252,6 +254,17 @@ pub fn build_microvm_for_boot( )?; } + // Attach virtio-mem device if configured + if let Some(memory_hotplug) = &vm_resources.memory_hotplug { + attach_virtio_mem_device( + &mut device_manager, + &vm, + &mut boot_cmdline, + memory_hotplug, + event_manager, + )?; + } + #[cfg(target_arch = "aarch64")] device_manager.attach_legacy_devices_aarch64( &vm, @@ -576,6 +589,29 @@ fn attach_entropy_device( device_manager.attach_virtio_device(vm, id, entropy_device.clone(), cmdline, false) } +fn attach_virtio_mem_device( + device_manager: &mut DeviceManager, + vm: &Arc, + cmdline: &mut LoaderKernelCmdline, + config: &MemoryHotplugConfig, + event_manager: &mut EventManager, +) -> Result<(), StartMicrovmError> { + let virtio_mem = Arc::new(Mutex::new( + VirtioMem::new( + Arc::clone(vm), + config.total_size_mib, + config.block_size_mib, + config.slot_size_mib, + ) + .map_err(|e| StartMicrovmError::Internal(VmmError::VirtioMem(e)))?, + )); + + let id = virtio_mem.lock().expect("Poisoned lock").id().to_string(); + event_manager.add_subscriber(virtio_mem.clone()); + device_manager.attach_virtio_device(vm, id, virtio_mem.clone(), cmdline, false)?; + Ok(()) +} + fn attach_block_devices<'a, I: Iterator>> + Debug>( device_manager: &mut DeviceManager, vm: &Arc, @@ -1200,4 +1236,42 @@ pub(crate) mod tests { "virtio_mmio.device=4K@0xc0001000:5" )); } + + pub(crate) fn insert_virtio_mem_device( + vmm: &mut Vmm, + cmdline: &mut Cmdline, + event_manager: &mut EventManager, + config: MemoryHotplugConfig, + ) { + attach_virtio_mem_device( + &mut vmm.device_manager, + &vmm.vm, + cmdline, + &config, + event_manager, + ) + .unwrap(); + } + + #[test] + fn test_attach_virtio_mem_device() { + let mut event_manager = EventManager::new().expect("Unable to create EventManager"); + let mut vmm = default_vmm(); + + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 128, + }; + + let mut cmdline = default_kernel_cmdline(); + insert_virtio_mem_device(&mut vmm, &mut cmdline, &mut event_manager, config); + + // Check if the vsock device is described in kernel_cmdline. + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + assert!(cmdline_contains( + &cmdline, + "virtio_mmio.device=4K@0xc0001000:5" + )); + } } diff --git a/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs b/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs index 2869f28ff4a..97e82a47a1c 100644 --- a/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs +++ b/src/vmm/src/cpu_config/aarch64/custom_cpu_template.rs @@ -17,7 +17,7 @@ use crate::cpu_config::templates::{ use crate::cpu_config::templates_serde::*; impl GetCpuTemplate for Option { - fn get_cpu_template(&self) -> Result, GetCpuTemplateError> { + fn get_cpu_template(&self) -> Result, GetCpuTemplateError> { match self { Some(template_type) => match template_type { CpuTemplateType::Custom(template) => Ok(Cow::Borrowed(template)), diff --git a/src/vmm/src/cpu_config/templates.rs b/src/vmm/src/cpu_config/templates.rs index 559da632cc4..bc558a457e4 100644 --- a/src/vmm/src/cpu_config/templates.rs +++ b/src/vmm/src/cpu_config/templates.rs @@ -49,7 +49,7 @@ pub enum GetCpuTemplateError { /// custom CPU templates and handle static CPU template and custom CPU template in a same manner. pub trait GetCpuTemplate { /// Get CPU template - fn get_cpu_template(&self) -> Result, GetCpuTemplateError>; + fn get_cpu_template(&self) -> Result, GetCpuTemplateError>; } /// Enum that represents types of cpu templates available. diff --git a/src/vmm/src/cpu_config/x86_64/custom_cpu_template.rs b/src/vmm/src/cpu_config/x86_64/custom_cpu_template.rs index 0d8917a4a5e..1e790f1a951 100644 --- a/src/vmm/src/cpu_config/x86_64/custom_cpu_template.rs +++ b/src/vmm/src/cpu_config/x86_64/custom_cpu_template.rs @@ -19,7 +19,7 @@ use crate::cpu_config::x86_64::static_cpu_templates::{StaticCpuTemplate, c3, t2, use crate::logger::warn; impl GetCpuTemplate for Option { - fn get_cpu_template(&self) -> Result, GetCpuTemplateError> { + fn get_cpu_template(&self) -> Result, GetCpuTemplateError> { use GetCpuTemplateError::*; match self { diff --git a/src/vmm/src/device_manager/pci_mngr.rs b/src/vmm/src/device_manager/pci_mngr.rs index f1ec39ab1d5..a6f01742256 100644 --- a/src/vmm/src/device_manager/pci_mngr.rs +++ b/src/vmm/src/device_manager/pci_mngr.rs @@ -20,6 +20,8 @@ use crate::devices::virtio::block::device::Block; use crate::devices::virtio::block::persist::{BlockConstructorArgs, BlockState}; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::generated::virtio_ids; +use crate::devices::virtio::mem::VirtioMem; +use crate::devices::virtio::mem::persist::{VirtioMemConstructorArgs, VirtioMemState}; use crate::devices::virtio::net::Net; use crate::devices::virtio::net::persist::{NetConstructorArgs, NetState}; use crate::devices::virtio::rng::Entropy; @@ -240,6 +242,8 @@ pub struct PciDevicesState { pub mmds: Option, /// Entropy device state. pub entropy_device: Option>, + /// Memory device state. + pub memory_device: Option>, } pub struct PciDevicesConstructorArgs<'a> { @@ -388,6 +392,20 @@ impl<'a> Persist<'a> for PciDevices { transport_state, }) } + virtio_ids::VIRTIO_ID_MEM => { + let mem_dev = locked_virtio_dev + .as_mut_any() + .downcast_mut::() + .unwrap(); + let device_state = mem_dev.save(); + + state.memory_device = Some(VirtioDeviceState { + device_id: mem_dev.id().to_string(), + pci_device_bdf, + device_state, + transport_state, + }) + } _ => unreachable!(), } } @@ -566,6 +584,29 @@ impl<'a> Persist<'a> for PciDevices { .unwrap() } + if let Some(memory_device) = &state.memory_device { + let ctor_args = VirtioMemConstructorArgs::new(Arc::clone(constructor_args.vm)); + + let device = Arc::new(Mutex::new( + VirtioMem::restore(ctor_args, &memory_device.device_state).unwrap(), + )); + + constructor_args + .vm_resources + .update_from_restored_device(SharedDeviceType::VirtioMem(device.clone())) + .unwrap(); + + pci_devices + .restore_pci_device( + constructor_args.vm, + device, + &memory_device.device_id, + &memory_device.transport_state, + constructor_args.event_manager, + ) + .unwrap() + } + Ok(pci_devices) } } @@ -583,6 +624,7 @@ mod tests { use crate::snapshot::Snapshot; use crate::vmm_config::balloon::BalloonDeviceConfig; use crate::vmm_config::entropy::EntropyDeviceConfig; + use crate::vmm_config::memory_hotplug::MemoryHotplugConfig; use crate::vmm_config::net::NetworkInterfaceConfig; use crate::vmm_config::vsock::VsockDeviceConfig; @@ -645,6 +687,18 @@ mod tests { let entropy_config = EntropyDeviceConfig::default(); insert_entropy_device(&mut vmm, &mut cmdline, &mut event_manager, entropy_config); + let memory_hotplug_config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 128, + }; + insert_virtio_mem_device( + &mut vmm, + &mut cmdline, + &mut event_manager, + memory_hotplug_config, + ); + Snapshot::new(vmm.device_manager.save()) .save(&mut buf.as_mut_slice()) .unwrap(); @@ -732,6 +786,11 @@ mod tests { }}, "entropy": {{ "rate_limiter": null + }}, + "memory-hotplug": {{ + "total_size_mib": 1024, + "block_size_mib": 2, + "slot_size_mib": 128 }} }}"#, _block_files.last().unwrap().as_path().to_str().unwrap(), diff --git a/src/vmm/src/device_manager/persist.rs b/src/vmm/src/device_manager/persist.rs index d6d46fff0f5..c9525365872 100644 --- a/src/vmm/src/device_manager/persist.rs +++ b/src/vmm/src/device_manager/persist.rs @@ -25,6 +25,10 @@ use crate::devices::virtio::block::device::Block; use crate::devices::virtio::block::persist::{BlockConstructorArgs, BlockState}; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::generated::virtio_ids; +use crate::devices::virtio::mem::VirtioMem; +use crate::devices::virtio::mem::persist::{ + VirtioMemConstructorArgs, VirtioMemPersistError, VirtioMemState, +}; use crate::devices::virtio::net::Net; use crate::devices::virtio::net::persist::{ NetConstructorArgs, NetPersistError as NetError, NetState, @@ -72,6 +76,8 @@ pub enum DevicePersistError { MmdsConfig(#[from] MmdsConfigError), /// Entropy: {0} Entropy(#[from] EntropyError), + /// virtio-mem: {0} + VirtioMem(#[from] VirtioMemPersistError), /// Resource misconfiguration: {0}. Is the snapshot file corrupted? ResourcesError(#[from] ResourcesError), /// Could not activate device: {0} @@ -125,6 +131,8 @@ pub struct DeviceStates { pub mmds: Option, /// Entropy device state. pub entropy_device: Option>, + /// Memory device state. + pub memory_device: Option>, } /// A type used to extract the concrete `Arc>` for each of the device @@ -136,6 +144,7 @@ pub enum SharedDeviceType { Balloon(Arc>), Vsock(Arc>>), Entropy(Arc>), + VirtioMem(Arc>), } pub struct MMIODevManagerConstructorArgs<'a> { @@ -335,6 +344,20 @@ impl<'a> Persist<'a> for MMIODeviceManager { device_info, }); } + virtio_ids::VIRTIO_ID_MEM => { + let mem = locked_device + .as_mut_any() + .downcast_mut::() + .unwrap(); + let device_state = mem.save(); + + states.memory_device = Some(VirtioDeviceState { + device_id, + device_state, + transport_state, + device_info, + }); + } _ => unreachable!(), }; @@ -549,6 +572,30 @@ impl<'a> Persist<'a> for MMIODeviceManager { )?; } + if let Some(memory_state) = &state.memory_device { + let ctor_args = VirtioMemConstructorArgs::new(Arc::clone(vm)); + + let device = Arc::new(Mutex::new(VirtioMem::restore( + ctor_args, + &memory_state.device_state, + )?)); + + constructor_args + .vm_resources + .update_from_restored_device(SharedDeviceType::VirtioMem(device.clone()))?; + + restore_helper( + device.clone(), + memory_state.device_state.virtio_state.activated, + false, + device, + &memory_state.device_id, + &memory_state.transport_state, + &memory_state.device_info, + constructor_args.event_manager, + )?; + } + Ok(dev_manager) } } @@ -565,6 +612,7 @@ mod tests { use crate::snapshot::Snapshot; use crate::vmm_config::balloon::BalloonDeviceConfig; use crate::vmm_config::entropy::EntropyDeviceConfig; + use crate::vmm_config::memory_hotplug::MemoryHotplugConfig; use crate::vmm_config::net::NetworkInterfaceConfig; use crate::vmm_config::vsock::VsockDeviceConfig; @@ -582,6 +630,7 @@ mod tests { && self.net_devices == other.net_devices && self.vsock_device == other.vsock_device && self.entropy_device == other.entropy_device + && self.memory_device == other.memory_device } } @@ -666,6 +715,18 @@ mod tests { let entropy_config = EntropyDeviceConfig::default(); insert_entropy_device(&mut vmm, &mut cmdline, &mut event_manager, entropy_config); + let memory_hotplug_config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 128, + }; + insert_virtio_mem_device( + &mut vmm, + &mut cmdline, + &mut event_manager, + memory_hotplug_config, + ); + Snapshot::new(vmm.device_manager.save()) .save(&mut buf.as_mut_slice()) .unwrap(); @@ -749,6 +810,11 @@ mod tests { }}, "entropy": {{ "rate_limiter": null + }}, + "memory-hotplug": {{ + "total_size_mib": 1024, + "block_size_mib": 2, + "slot_size_mib": 128 }} }}"#, _block_files.last().unwrap().as_path().to_str().unwrap(), diff --git a/src/vmm/src/devices/legacy/i8042.rs b/src/vmm/src/devices/legacy/i8042.rs index 235ce2a7339..eee9957f208 100644 --- a/src/vmm/src/devices/legacy/i8042.rs +++ b/src/vmm/src/devices/legacy/i8042.rs @@ -230,11 +230,10 @@ impl vm_device::BusDevice for I8042Device { // Check if we still have data in the internal buffer. If so, we need to trigger // another interrupt, to let the guest know they need to issue another read from // port 0x60. - if (self.status & SB_OUT_DATA_AVAIL) != 0 { - if let Err(I8042Error::KbdInterruptFailure(err)) = self.trigger_kbd_interrupt() - { - warn!("Failed to trigger i8042 kbd interrupt {:?}", err); - } + if (self.status & SB_OUT_DATA_AVAIL) != 0 + && let Err(I8042Error::KbdInterruptFailure(err)) = self.trigger_kbd_interrupt() + { + warn!("Failed to trigger i8042 kbd interrupt {:?}", err); } } _ => read_ok = false, diff --git a/src/vmm/src/devices/legacy/serial.rs b/src/vmm/src/devices/legacy/serial.rs index 83e84a7bf56..63834af3cb1 100644 --- a/src/vmm/src/devices/legacy/serial.rs +++ b/src/vmm/src/devices/legacy/serial.rs @@ -333,10 +333,10 @@ impl MutEventSubscriber // Therefore, only try to register stdin to epoll if it is a terminal or a FIFO pipe. // SAFETY: isatty has no invariants that need to be upheld. If serial_fd is an invalid // argument, it will return 0 and set errno to EBADF. - if unsafe { libc::isatty(serial_fd) } == 1 || is_fifo(serial_fd) { - if let Err(err) = ops.add(Events::new(&serial_fd, EventSet::IN)) { - warn!("Failed to register serial input fd: {}", err); - } + if (unsafe { libc::isatty(serial_fd) } == 1 || is_fifo(serial_fd)) + && let Err(err) = ops.add(Events::new(&serial_fd, EventSet::IN)) + { + warn!("Failed to register serial input fd: {}", err); } if let Err(err) = ops.add(Events::new(&buf_ready_evt, EventSet::IN)) { warn!("Failed to register serial buffer ready event: {}", err); diff --git a/src/vmm/src/devices/virtio/block/device.rs b/src/vmm/src/devices/virtio/block/device.rs index 93eb56e7760..13155efb31d 100644 --- a/src/vmm/src/devices/virtio/block/device.rs +++ b/src/vmm/src/devices/virtio/block/device.rs @@ -41,7 +41,7 @@ impl Block { VhostUserBlock::new(config).map_err(BlockError::VhostUserBackend)?, )) } else { - return Err(BlockError::InvalidBlockConfig); + Err(BlockError::InvalidBlockConfig) } } diff --git a/src/vmm/src/devices/virtio/block/virtio/device.rs b/src/vmm/src/devices/virtio/block/virtio/device.rs index 62ebdbbf5fd..ecdd8ee4f6d 100644 --- a/src/vmm/src/devices/virtio/block/virtio/device.rs +++ b/src/vmm/src/devices/virtio/block/virtio/device.rs @@ -455,10 +455,10 @@ impl VirtioBlock { }); } - if let FileEngine::Async(ref mut engine) = self.disk.file_engine { - if let Err(err) = engine.kick_submission_queue() { - error!("BlockError submitting pending block requests: {:?}", err); - } + if let FileEngine::Async(ref mut engine) = self.disk.file_engine + && let Err(err) = engine.kick_submission_queue() + { + error!("BlockError submitting pending block requests: {:?}", err); } if !used_any { diff --git a/src/vmm/src/devices/virtio/block/virtio/event_handler.rs b/src/vmm/src/devices/virtio/block/virtio/event_handler.rs index 03c09a01972..9f02862f814 100644 --- a/src/vmm/src/devices/virtio/block/virtio/event_handler.rs +++ b/src/vmm/src/devices/virtio/block/virtio/event_handler.rs @@ -29,14 +29,14 @@ impl VirtioBlock { )) { error!("Failed to register ratelimiter event: {}", err); } - if let FileEngine::Async(ref engine) = self.disk.file_engine { - if let Err(err) = ops.add(Events::with_data( + if let FileEngine::Async(ref engine) = self.disk.file_engine + && let Err(err) = ops.add(Events::with_data( engine.completion_evt(), Self::PROCESS_ASYNC_COMPLETION, EventSet::IN, - )) { - error!("Failed to register IO engine completion event: {}", err); - } + )) + { + error!("Failed to register IO engine completion event: {}", err); } } diff --git a/src/vmm/src/devices/virtio/generated/mod.rs b/src/vmm/src/devices/virtio/generated/mod.rs index a9d1f08f88f..712284e9359 100644 --- a/src/vmm/src/devices/virtio/generated/mod.rs +++ b/src/vmm/src/devices/virtio/generated/mod.rs @@ -13,5 +13,6 @@ pub mod virtio_blk; pub mod virtio_config; pub mod virtio_ids; +pub mod virtio_mem; pub mod virtio_net; pub mod virtio_ring; diff --git a/src/vmm/src/devices/virtio/generated/virtio_mem.rs b/src/vmm/src/devices/virtio/generated/virtio_mem.rs new file mode 100644 index 00000000000..e3c25ff0bb9 --- /dev/null +++ b/src/vmm/src/devices/virtio/generated/virtio_mem.rs @@ -0,0 +1,244 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// automatically generated by tools/bindgen.sh + +#![allow( + non_camel_case_types, + non_upper_case_globals, + dead_code, + non_snake_case, + clippy::ptr_as_ptr, + clippy::undocumented_unsafe_blocks, + missing_debug_implementations, + clippy::tests_outside_test_module, + unsafe_op_in_unsafe_fn, + clippy::redundant_static_lifetimes +)] + +pub const VIRTIO_MEM_F_ACPI_PXM: u32 = 0; +pub const VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: u32 = 1; +pub const VIRTIO_MEM_F_PERSISTENT_SUSPEND: u32 = 2; +pub const VIRTIO_MEM_REQ_PLUG: u32 = 0; +pub const VIRTIO_MEM_REQ_UNPLUG: u32 = 1; +pub const VIRTIO_MEM_REQ_UNPLUG_ALL: u32 = 2; +pub const VIRTIO_MEM_REQ_STATE: u32 = 3; +pub const VIRTIO_MEM_RESP_ACK: u32 = 0; +pub const VIRTIO_MEM_RESP_NACK: u32 = 1; +pub const VIRTIO_MEM_RESP_BUSY: u32 = 2; +pub const VIRTIO_MEM_RESP_ERROR: u32 = 3; +pub const VIRTIO_MEM_STATE_PLUGGED: u32 = 0; +pub const VIRTIO_MEM_STATE_UNPLUGGED: u32 = 1; +pub const VIRTIO_MEM_STATE_MIXED: u32 = 2; +pub type __u8 = ::std::os::raw::c_uchar; +pub type __u16 = ::std::os::raw::c_ushort; +pub type __u64 = ::std::os::raw::c_ulonglong; +pub type __le16 = __u16; +pub type __le64 = __u64; +pub type __virtio16 = __u16; +pub type __virtio64 = __u64; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_mem_req_plug { + pub addr: __virtio64, + pub nb_blocks: __virtio16, + pub padding: [__virtio16; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_req_plug"][::std::mem::size_of::() - 16usize]; + ["Alignment of virtio_mem_req_plug"][::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_req_plug::addr"] + [::std::mem::offset_of!(virtio_mem_req_plug, addr) - 0usize]; + ["Offset of field: virtio_mem_req_plug::nb_blocks"] + [::std::mem::offset_of!(virtio_mem_req_plug, nb_blocks) - 8usize]; + ["Offset of field: virtio_mem_req_plug::padding"] + [::std::mem::offset_of!(virtio_mem_req_plug, padding) - 10usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_mem_req_unplug { + pub addr: __virtio64, + pub nb_blocks: __virtio16, + pub padding: [__virtio16; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_req_unplug"][::std::mem::size_of::() - 16usize]; + ["Alignment of virtio_mem_req_unplug"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_req_unplug::addr"] + [::std::mem::offset_of!(virtio_mem_req_unplug, addr) - 0usize]; + ["Offset of field: virtio_mem_req_unplug::nb_blocks"] + [::std::mem::offset_of!(virtio_mem_req_unplug, nb_blocks) - 8usize]; + ["Offset of field: virtio_mem_req_unplug::padding"] + [::std::mem::offset_of!(virtio_mem_req_unplug, padding) - 10usize]; +}; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_mem_req_state { + pub addr: __virtio64, + pub nb_blocks: __virtio16, + pub padding: [__virtio16; 3usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_req_state"][::std::mem::size_of::() - 16usize]; + ["Alignment of virtio_mem_req_state"][::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_req_state::addr"] + [::std::mem::offset_of!(virtio_mem_req_state, addr) - 0usize]; + ["Offset of field: virtio_mem_req_state::nb_blocks"] + [::std::mem::offset_of!(virtio_mem_req_state, nb_blocks) - 8usize]; + ["Offset of field: virtio_mem_req_state::padding"] + [::std::mem::offset_of!(virtio_mem_req_state, padding) - 10usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct virtio_mem_req { + pub type_: __virtio16, + pub padding: [__virtio16; 3usize], + pub u: virtio_mem_req__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union virtio_mem_req__bindgen_ty_1 { + pub plug: virtio_mem_req_plug, + pub unplug: virtio_mem_req_unplug, + pub state: virtio_mem_req_state, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_req__bindgen_ty_1"] + [::std::mem::size_of::() - 16usize]; + ["Alignment of virtio_mem_req__bindgen_ty_1"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_req__bindgen_ty_1::plug"] + [::std::mem::offset_of!(virtio_mem_req__bindgen_ty_1, plug) - 0usize]; + ["Offset of field: virtio_mem_req__bindgen_ty_1::unplug"] + [::std::mem::offset_of!(virtio_mem_req__bindgen_ty_1, unplug) - 0usize]; + ["Offset of field: virtio_mem_req__bindgen_ty_1::state"] + [::std::mem::offset_of!(virtio_mem_req__bindgen_ty_1, state) - 0usize]; +}; +impl Default for virtio_mem_req__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_req"][::std::mem::size_of::() - 24usize]; + ["Alignment of virtio_mem_req"][::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_req::type_"] + [::std::mem::offset_of!(virtio_mem_req, type_) - 0usize]; + ["Offset of field: virtio_mem_req::padding"] + [::std::mem::offset_of!(virtio_mem_req, padding) - 2usize]; + ["Offset of field: virtio_mem_req::u"][::std::mem::offset_of!(virtio_mem_req, u) - 8usize]; +}; +impl Default for virtio_mem_req { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_mem_resp_state { + pub state: __virtio16, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_resp_state"][::std::mem::size_of::() - 2usize]; + ["Alignment of virtio_mem_resp_state"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_mem_resp_state::state"] + [::std::mem::offset_of!(virtio_mem_resp_state, state) - 0usize]; +}; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct virtio_mem_resp { + pub type_: __virtio16, + pub padding: [__virtio16; 3usize], + pub u: virtio_mem_resp__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union virtio_mem_resp__bindgen_ty_1 { + pub state: virtio_mem_resp_state, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_resp__bindgen_ty_1"] + [::std::mem::size_of::() - 2usize]; + ["Alignment of virtio_mem_resp__bindgen_ty_1"] + [::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_mem_resp__bindgen_ty_1::state"] + [::std::mem::offset_of!(virtio_mem_resp__bindgen_ty_1, state) - 0usize]; +}; +impl Default for virtio_mem_resp__bindgen_ty_1 { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_resp"][::std::mem::size_of::() - 10usize]; + ["Alignment of virtio_mem_resp"][::std::mem::align_of::() - 2usize]; + ["Offset of field: virtio_mem_resp::type_"] + [::std::mem::offset_of!(virtio_mem_resp, type_) - 0usize]; + ["Offset of field: virtio_mem_resp::padding"] + [::std::mem::offset_of!(virtio_mem_resp, padding) - 2usize]; + ["Offset of field: virtio_mem_resp::u"][::std::mem::offset_of!(virtio_mem_resp, u) - 8usize]; +}; +impl Default for virtio_mem_resp { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq)] +pub struct virtio_mem_config { + pub block_size: __le64, + pub node_id: __le16, + pub padding: [__u8; 6usize], + pub addr: __le64, + pub region_size: __le64, + pub usable_region_size: __le64, + pub plugged_size: __le64, + pub requested_size: __le64, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of virtio_mem_config"][::std::mem::size_of::() - 56usize]; + ["Alignment of virtio_mem_config"][::std::mem::align_of::() - 8usize]; + ["Offset of field: virtio_mem_config::block_size"] + [::std::mem::offset_of!(virtio_mem_config, block_size) - 0usize]; + ["Offset of field: virtio_mem_config::node_id"] + [::std::mem::offset_of!(virtio_mem_config, node_id) - 8usize]; + ["Offset of field: virtio_mem_config::padding"] + [::std::mem::offset_of!(virtio_mem_config, padding) - 10usize]; + ["Offset of field: virtio_mem_config::addr"] + [::std::mem::offset_of!(virtio_mem_config, addr) - 16usize]; + ["Offset of field: virtio_mem_config::region_size"] + [::std::mem::offset_of!(virtio_mem_config, region_size) - 24usize]; + ["Offset of field: virtio_mem_config::usable_region_size"] + [::std::mem::offset_of!(virtio_mem_config, usable_region_size) - 32usize]; + ["Offset of field: virtio_mem_config::plugged_size"] + [::std::mem::offset_of!(virtio_mem_config, plugged_size) - 40usize]; + ["Offset of field: virtio_mem_config::requested_size"] + [::std::mem::offset_of!(virtio_mem_config, requested_size) - 48usize]; +}; diff --git a/src/vmm/src/devices/virtio/iovec.rs b/src/vmm/src/devices/virtio/iovec.rs index 80c5071fbe6..3a2703de82e 100644 --- a/src/vmm/src/devices/virtio/iovec.rs +++ b/src/vmm/src/devices/virtio/iovec.rs @@ -569,7 +569,7 @@ mod tests { ]) } - fn chain(m: &GuestMemoryMmap, is_write_only: bool) -> (Queue, VirtQueue) { + fn chain(m: &GuestMemoryMmap, is_write_only: bool) -> (Queue, VirtQueue<'_>) { let vq = VirtQueue::new(GuestAddress(0), m, 16); let mut q = vq.create_queue(); @@ -593,14 +593,14 @@ mod tests { (q, vq) } - fn read_only_chain(mem: &GuestMemoryMmap) -> (Queue, VirtQueue) { + fn read_only_chain(mem: &GuestMemoryMmap) -> (Queue, VirtQueue<'_>) { let v: Vec = (0..=255).collect(); mem.write_slice(&v, GuestAddress(0x20000)).unwrap(); chain(mem, false) } - fn write_only_chain(mem: &GuestMemoryMmap) -> (Queue, VirtQueue) { + fn write_only_chain(mem: &GuestMemoryMmap) -> (Queue, VirtQueue<'_>) { let v = vec![0; 256]; mem.write_slice(&v, GuestAddress(0x20000)).unwrap(); diff --git a/src/vmm/src/devices/virtio/mem/device.rs b/src/vmm/src/devices/virtio/mem/device.rs new file mode 100644 index 00000000000..0a1a5e0580a --- /dev/null +++ b/src/vmm/src/devices/virtio/mem/device.rs @@ -0,0 +1,436 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::io; +use std::ops::Deref; +use std::sync::Arc; +use std::sync::atomic::AtomicU32; + +use log::info; +use serde::{Deserialize, Serialize}; +use vm_memory::{ + Address, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryRegion, GuestUsize, +}; +use vmm_sys_util::eventfd::EventFd; + +use super::{MEM_NUM_QUEUES, MEM_QUEUE}; +use crate::devices::DeviceError; +use crate::devices::virtio::ActivateError; +use crate::devices::virtio::device::{ActiveState, DeviceState, VirtioDevice}; +use crate::devices::virtio::generated::virtio_config::VIRTIO_F_VERSION_1; +use crate::devices::virtio::generated::virtio_ids::VIRTIO_ID_MEM; +use crate::devices::virtio::generated::virtio_mem::{ + VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, virtio_mem_config, +}; +use crate::devices::virtio::iov_deque::IovDequeError; +use crate::devices::virtio::mem::metrics::METRICS; +use crate::devices::virtio::mem::{VIRTIO_MEM_DEV_ID, VIRTIO_MEM_GUEST_ADDRESS}; +use crate::devices::virtio::queue::{FIRECRACKER_MAX_QUEUE_SIZE, InvalidAvailIdx, Queue}; +use crate::devices::virtio::transport::{VirtioInterrupt, VirtioInterruptType}; +use crate::logger::{IncMetric, debug, error}; +use crate::utils::{bytes_to_mib, mib_to_bytes, u64_to_usize, usize_to_u64}; +use crate::vstate::memory::{ByteValued, GuestMemoryMmap, GuestRegionMmap}; +use crate::vstate::vm::VmError; +use crate::{Vm, impl_device_type}; + +// SAFETY: virtio_mem_config only contains plain data types +unsafe impl ByteValued for virtio_mem_config {} + +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum VirtioMemError { + /// Error while handling an Event file descriptor: {0} + EventFd(#[from] io::Error), + /// Received error while sending an interrupt: {0} + InterruptError(std::io::Error), +} + +#[derive(Debug)] +pub struct VirtioMem { + // VirtIO fields + avail_features: u64, + acked_features: u64, + activate_event: EventFd, + + // Transport fields + device_state: DeviceState, + pub(crate) queues: Vec, + queue_events: Vec, + + // Device specific fields + pub(crate) config: virtio_mem_config, + pub(crate) slot_size: usize, + vm: Arc, +} + +/// Memory hotplug device status information. +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct VirtioMemStatus { + /// Block size in MiB. + pub block_size_mib: usize, + /// Total memory size in MiB that can be hotplugged. + pub total_size_mib: usize, + /// Size of the KVM slots in MiB. + pub slot_size_mib: usize, + /// Currently plugged memory size in MiB. + pub plugged_size_mib: usize, + /// Requested memory size in MiB. + pub requested_size_mib: usize, +} + +impl VirtioMem { + pub fn new( + vm: Arc, + total_size_mib: usize, + block_size_mib: usize, + slot_size_mib: usize, + ) -> Result { + let queues = vec![Queue::new(FIRECRACKER_MAX_QUEUE_SIZE); MEM_NUM_QUEUES]; + let config = virtio_mem_config { + addr: VIRTIO_MEM_GUEST_ADDRESS.raw_value(), + region_size: mib_to_bytes(total_size_mib) as u64, + block_size: mib_to_bytes(block_size_mib) as u64, + ..Default::default() + }; + + Self::from_state(vm, queues, config, mib_to_bytes(slot_size_mib)) + } + + pub fn from_state( + vm: Arc, + queues: Vec, + config: virtio_mem_config, + slot_size: usize, + ) -> Result { + let activate_event = EventFd::new(libc::EFD_NONBLOCK)?; + let queue_events = (0..MEM_NUM_QUEUES) + .map(|_| EventFd::new(libc::EFD_NONBLOCK)) + .collect::, io::Error>>()?; + + Ok(Self { + avail_features: (1 << VIRTIO_F_VERSION_1) | (1 << VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE), + acked_features: 0u64, + activate_event, + device_state: DeviceState::Inactive, + queues, + queue_events, + config, + vm, + slot_size, + }) + } + + pub fn id(&self) -> &str { + VIRTIO_MEM_DEV_ID + } + + /// Gets the total hotpluggable size. + pub fn total_size_mib(&self) -> usize { + bytes_to_mib(u64_to_usize(self.config.region_size)) + } + + /// Gets the block size. + pub fn block_size_mib(&self) -> usize { + bytes_to_mib(u64_to_usize(self.config.block_size)) + } + + /// Gets the block size. + pub fn slot_size_mib(&self) -> usize { + bytes_to_mib(self.slot_size) + } + + /// Gets the total size of the plugged memory blocks. + pub fn plugged_size_mib(&self) -> usize { + bytes_to_mib(u64_to_usize(self.config.plugged_size)) + } + + /// Gets the requested size + pub fn requested_size_mib(&self) -> usize { + bytes_to_mib(u64_to_usize(self.config.requested_size)) + } + + pub fn status(&self) -> VirtioMemStatus { + VirtioMemStatus { + block_size_mib: self.block_size_mib(), + total_size_mib: self.total_size_mib(), + slot_size_mib: self.slot_size_mib(), + plugged_size_mib: self.plugged_size_mib(), + requested_size_mib: self.requested_size_mib(), + } + } + + fn signal_used_queue(&self) -> Result<(), VirtioMemError> { + self.interrupt_trigger() + .trigger(VirtioInterruptType::Queue(MEM_QUEUE.try_into().unwrap())) + .map_err(VirtioMemError::InterruptError) + } + + fn process_mem_queue(&mut self) -> Result<(), VirtioMemError> { + info!("TODO: Received mem queue event, but it's not implemented."); + Ok(()) + } + + pub(crate) fn process_mem_queue_event(&mut self) { + METRICS.queue_event_count.inc(); + if let Err(err) = self.queue_events[MEM_QUEUE].read() { + METRICS.queue_event_fails.inc(); + error!("Failed to read mem queue event: {err}"); + return; + } + + if let Err(err) = self.process_mem_queue() { + METRICS.queue_event_fails.inc(); + error!("virtio-mem: Failed to process queue: {err}"); + } + } + + pub fn process_virtio_queues(&mut self) -> Result<(), VirtioMemError> { + self.process_mem_queue() + } + + pub(crate) fn set_avail_features(&mut self, features: u64) { + self.avail_features = features; + } + + pub(crate) fn set_acked_features(&mut self, features: u64) { + self.acked_features = features; + } + + pub(crate) fn activate_event(&self) -> &EventFd { + &self.activate_event + } +} + +impl VirtioDevice for VirtioMem { + impl_device_type!(VIRTIO_ID_MEM); + + fn queues(&self) -> &[Queue] { + &self.queues + } + + fn queues_mut(&mut self) -> &mut [Queue] { + &mut self.queues + } + + fn queue_events(&self) -> &[EventFd] { + &self.queue_events + } + + fn interrupt_trigger(&self) -> &dyn VirtioInterrupt { + self.device_state + .active_state() + .expect("Device is not activated") + .interrupt + .deref() + } + + fn avail_features(&self) -> u64 { + self.avail_features + } + + fn acked_features(&self) -> u64 { + self.acked_features + } + + fn set_acked_features(&mut self, acked_features: u64) { + self.acked_features = acked_features; + } + + fn read_config(&self, offset: u64, data: &mut [u8]) { + let offset = u64_to_usize(offset); + self.config + .as_slice() + .get(offset..offset + data.len()) + .map(|s| data.copy_from_slice(s)) + .unwrap_or_else(|| { + error!( + "virtio-mem: Config read offset+length {offset}+{} out of bounds", + data.len() + ) + }) + } + + fn write_config(&mut self, offset: u64, _data: &[u8]) { + error!("virtio-mem: Attempted write to read-only config space at offset {offset}"); + } + + fn is_activated(&self) -> bool { + self.device_state.is_activated() + } + + fn activate( + &mut self, + mem: GuestMemoryMmap, + interrupt: Arc, + ) -> Result<(), ActivateError> { + if (self.acked_features & (1 << VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE)) == 0 { + error!( + "virtio-mem: VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE feature not acknowledged by guest" + ); + METRICS.activate_fails.inc(); + return Err(ActivateError::RequiredFeatureNotAcked( + "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE", + )); + } + + for q in self.queues.iter_mut() { + q.initialize(&mem) + .map_err(ActivateError::QueueMemoryError)?; + } + + self.device_state = DeviceState::Activated(ActiveState { mem, interrupt }); + if self.activate_event.write(1).is_err() { + METRICS.activate_fails.inc(); + self.device_state = DeviceState::Inactive; + return Err(ActivateError::EventFd); + } + + Ok(()) + } +} + +#[cfg(test)] +pub(crate) mod test_utils { + use super::*; + use crate::vstate::vm::tests::setup_vm_with_memory; + + pub(crate) fn default_virtio_mem() -> VirtioMem { + let (_, vm) = setup_vm_with_memory(0x1000); + let vm = Arc::new(vm); + VirtioMem::new(vm, 1024, 2, 128).unwrap() + } +} + +#[cfg(test)] +mod tests { + use std::ptr::null_mut; + + use vm_memory::mmap::MmapRegionBuilder; + + use super::*; + use crate::devices::virtio::device::VirtioDevice; + use crate::devices::virtio::mem::device::test_utils::default_virtio_mem; + use crate::vstate::vm::tests::setup_vm_with_memory; + + #[test] + fn test_new() { + let mem = default_virtio_mem(); + + assert_eq!(mem.total_size_mib(), 1024); + assert_eq!(mem.block_size_mib(), 2); + assert_eq!(mem.plugged_size_mib(), 0); + assert_eq!(mem.id(), VIRTIO_MEM_DEV_ID); + assert_eq!(mem.device_type(), VIRTIO_ID_MEM); + + let features = (1 << VIRTIO_F_VERSION_1) | (1 << VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE); + assert_eq!(mem.avail_features(), features); + assert_eq!(mem.acked_features(), 0); + + assert!(!mem.is_activated()); + + assert_eq!(mem.queues().len(), MEM_NUM_QUEUES); + assert_eq!(mem.queue_events().len(), MEM_NUM_QUEUES); + } + + #[test] + fn test_from_state() { + let (_, vm) = setup_vm_with_memory(0x1000); + let vm = Arc::new(vm); + let queues = vec![Queue::new(FIRECRACKER_MAX_QUEUE_SIZE); MEM_NUM_QUEUES]; + let region_size_mib = 2048; + let block_size_mib = 2; + let slot_size_mib = 128; + let plugged_size_mib = 512; + let usable_region_size = mib_to_bytes(1024) as u64; + let config = virtio_mem_config { + addr: VIRTIO_MEM_GUEST_ADDRESS.raw_value(), + region_size: mib_to_bytes(region_size_mib) as u64, + block_size: mib_to_bytes(block_size_mib) as u64, + plugged_size: mib_to_bytes(plugged_size_mib) as u64, + usable_region_size, + ..Default::default() + }; + let mem = VirtioMem::from_state(vm, queues, config, mib_to_bytes(slot_size_mib)).unwrap(); + assert_eq!(mem.total_size_mib(), region_size_mib); + assert_eq!(mem.block_size_mib(), block_size_mib); + assert_eq!(mem.slot_size_mib(), slot_size_mib); + assert_eq!(mem.plugged_size_mib(), plugged_size_mib); + assert_eq!(mem.config.usable_region_size, usable_region_size); + } + + #[test] + fn test_read_config() { + let mem = default_virtio_mem(); + let mut data = [0u8; 8]; + + mem.read_config(0, &mut data); + assert_eq!( + u64::from_le_bytes(data), + mib_to_bytes(mem.block_size_mib()) as u64 + ); + + mem.read_config(16, &mut data); + assert_eq!( + u64::from_le_bytes(data), + VIRTIO_MEM_GUEST_ADDRESS.raw_value() + ); + + mem.read_config(24, &mut data); + assert_eq!( + u64::from_le_bytes(data), + mib_to_bytes(mem.total_size_mib()) as u64 + ); + } + + #[test] + fn test_read_config_out_of_bounds() { + let mem = default_virtio_mem(); + + let mut data = [0u8; 8]; + let config_size = std::mem::size_of::(); + mem.read_config(config_size as u64, &mut data); + assert_eq!(data, [0u8; 8]); // Should remain unchanged + + let mut data = vec![0u8; config_size]; + mem.read_config(8, &mut data); + assert_eq!(data, vec![0u8; config_size]); // Should remain unchanged + } + + #[test] + fn test_write_config() { + let mut mem = default_virtio_mem(); + let data = [1u8; 8]; + mem.write_config(0, &data); // Should log error but not crash + + // should not change config + let mut data = [0u8; 8]; + mem.read_config(0, &mut data); + let block_size = u64::from_le_bytes(data); + assert_eq!(block_size, mib_to_bytes(2) as u64); + } + + #[test] + fn test_set_features() { + let mut mem = default_virtio_mem(); + mem.set_avail_features(123); + assert_eq!(mem.avail_features(), 123); + mem.set_acked_features(456); + assert_eq!(mem.acked_features(), 456); + } + + #[test] + fn test_status() { + let mut mem = default_virtio_mem(); + let status = mem.status(); + assert_eq!( + status, + VirtioMemStatus { + block_size_mib: 2, + total_size_mib: 1024, + slot_size_mib: 128, + plugged_size_mib: 0, + requested_size_mib: 0, + } + ); + } +} diff --git a/src/vmm/src/devices/virtio/mem/event_handler.rs b/src/vmm/src/devices/virtio/mem/event_handler.rs new file mode 100644 index 00000000000..ae81ef12a64 --- /dev/null +++ b/src/vmm/src/devices/virtio/mem/event_handler.rs @@ -0,0 +1,192 @@ +// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use event_manager::{EventOps, Events, MutEventSubscriber}; +use vmm_sys_util::epoll::EventSet; + +use crate::devices::virtio::device::VirtioDevice; +use crate::devices::virtio::mem::MEM_QUEUE; +use crate::devices::virtio::mem::device::VirtioMem; +use crate::logger::{error, warn}; + +impl VirtioMem { + const PROCESS_ACTIVATE: u32 = 0; + const PROCESS_MEM_QUEUE: u32 = 1; + + fn register_runtime_events(&self, ops: &mut EventOps) { + if let Err(err) = ops.add(Events::with_data( + &self.queue_events()[MEM_QUEUE], + Self::PROCESS_MEM_QUEUE, + EventSet::IN, + )) { + error!("virtio-mem: Failed to register queue event: {err}"); + } + } + + fn register_activate_event(&self, ops: &mut EventOps) { + if let Err(err) = ops.add(Events::with_data( + self.activate_event(), + Self::PROCESS_ACTIVATE, + EventSet::IN, + )) { + error!("virtio-mem: Failed to register activate event: {err}"); + } + } + + fn process_activate_event(&self, ops: &mut EventOps) { + if let Err(err) = self.activate_event().read() { + error!("virtio-mem: Failed to consume activate event: {err}"); + } + + // Register runtime events + self.register_runtime_events(ops); + + // Remove activate event + if let Err(err) = ops.remove(Events::with_data( + self.activate_event(), + Self::PROCESS_ACTIVATE, + EventSet::IN, + )) { + error!("virtio-mem: Failed to un-register activate event: {err}"); + } + } +} + +impl MutEventSubscriber for VirtioMem { + fn init(&mut self, ops: &mut event_manager::EventOps) { + // This function can be called during different points in the device lifetime: + // - shortly after device creation, + // - on device activation (is-activated already true at this point), + // - on device restore from snapshot. + if self.is_activated() { + self.register_runtime_events(ops); + } else { + self.register_activate_event(ops); + } + } + + fn process(&mut self, events: event_manager::Events, ops: &mut event_manager::EventOps) { + let event_set = events.event_set(); + let source = events.data(); + + if !event_set.contains(EventSet::IN) { + warn!("virtio-mem: Received unknown event: {event_set:?} from source {source}"); + return; + } + + if !self.is_activated() { + warn!("virtio-mem: The device is not activated yet. Spurious event received: {source}"); + return; + } + + match source { + Self::PROCESS_ACTIVATE => self.process_activate_event(ops), + Self::PROCESS_MEM_QUEUE => self.process_mem_queue_event(), + + _ => { + warn!("virtio-mem: Unknown event received: {source}"); + } + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::{Arc, Mutex}; + + use event_manager::{EventManager, SubscriberOps}; + use vmm_sys_util::epoll::EventSet; + + use super::*; + use crate::devices::virtio::ActivateError; + use crate::devices::virtio::generated::virtio_mem::VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE; + use crate::devices::virtio::mem::device::test_utils::default_virtio_mem; + use crate::devices::virtio::test_utils::{VirtQueue, default_interrupt, default_mem}; + use crate::vstate::memory::GuestAddress; + + #[test] + fn test_event_handler_activation() { + let mut event_manager = EventManager::new().unwrap(); + let mut mem_device = default_virtio_mem(); + let mem = default_mem(); + let interrupt = default_interrupt(); + + // Set up queue + let virtq = VirtQueue::new(GuestAddress(0), &mem, 16); + mem_device.queues_mut()[MEM_QUEUE] = virtq.create_queue(); + + let mem_device = Arc::new(Mutex::new(mem_device)); + let _id = event_manager.add_subscriber(mem_device.clone()); + + // Device should register activate event when inactive + assert!(!mem_device.lock().unwrap().is_activated()); + + // Device should prevent activation before features are acked + let err = mem_device + .lock() + .unwrap() + .activate(mem.clone(), interrupt.clone()) + .unwrap_err(); + + assert!(matches!(err, ActivateError::RequiredFeatureNotAcked(_))); + + // Ack the feature and activate the device + mem_device + .lock() + .unwrap() + .set_acked_features(1 << VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE); + + mem_device.lock().unwrap().activate(mem, interrupt).unwrap(); + + // Process activation event + let ev_count = event_manager.run_with_timeout(50).unwrap(); + assert_eq!(ev_count, 1); + assert!(mem_device.lock().unwrap().is_activated()); + } + + #[test] + fn test_process_mem_queue_event() { + let mut event_manager = EventManager::new().unwrap(); + let mut mem_device = default_virtio_mem(); + let mem = default_mem(); + let interrupt = default_interrupt(); + + // Set up queue + let virtq = VirtQueue::new(GuestAddress(0), &mem, 16); + mem_device.queues_mut()[MEM_QUEUE] = virtq.create_queue(); + mem_device.set_acked_features(mem_device.avail_features()); + + let mem_device = Arc::new(Mutex::new(mem_device)); + let _id = event_manager.add_subscriber(mem_device.clone()); + + // Activate device first + mem_device.lock().unwrap().activate(mem, interrupt).unwrap(); + event_manager.run_with_timeout(50).unwrap(); // Process activation + + // Trigger queue event + mem_device.lock().unwrap().queue_events()[MEM_QUEUE] + .write(1) + .unwrap(); + + // Process queue event + let ev_count = event_manager.run_with_timeout(50).unwrap(); + assert_eq!(ev_count, 1); + } + + #[test] + fn test_spurious_event_before_activation() { + let mut event_manager = EventManager::new().unwrap(); + let mem_device = default_virtio_mem(); + let mem_device = Arc::new(Mutex::new(mem_device)); + let _id = event_manager.add_subscriber(mem_device.clone()); + + // Try to trigger queue event before activation + mem_device.lock().unwrap().queue_events()[MEM_QUEUE] + .write(1) + .unwrap(); + + // Should not process queue events before activation + let ev_count = event_manager.run_with_timeout(50).unwrap(); + assert_eq!(ev_count, 0); + } +} diff --git a/src/vmm/src/devices/virtio/mem/metrics.rs b/src/vmm/src/devices/virtio/mem/metrics.rs new file mode 100644 index 00000000000..443e9a8b8f1 --- /dev/null +++ b/src/vmm/src/devices/virtio/mem/metrics.rs @@ -0,0 +1,78 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Defines the metrics system for memory devices. +//! +//! # Metrics format +//! The metrics are flushed in JSON when requested by vmm::logger::metrics::METRICS.write(). +//! +//! ## JSON example with metrics: +//! ```json +//! "memory_hotplug": { +//! "activate_fails": "SharedIncMetric", +//! "queue_event_fails": "SharedIncMetric", +//! "queue_event_count": "SharedIncMetric", +//! ... +//! } +//! } +//! ``` +//! Each `memory` field in the example above is a serializable `VirtioMemDeviceMetrics` structure +//! collecting metrics such as `activate_fails`, `queue_event_fails` etc. for the memoty hotplug +//! device. +//! Since Firecrakcer only supports one virtio-mem device, there is no per device metrics and +//! `memory_hotplug` represents the aggregate entropy metrics. + +use serde::ser::SerializeMap; +use serde::{Serialize, Serializer}; + +use crate::logger::{LatencyAggregateMetrics, SharedIncMetric}; + +/// Stores aggregated virtio-mem metrics +pub(super) static METRICS: VirtioMemDeviceMetrics = VirtioMemDeviceMetrics::new(); + +/// Called by METRICS.flush(), this function facilitates serialization of virtio-mem device metrics. +pub fn flush_metrics(serializer: S) -> Result { + let mut seq = serializer.serialize_map(Some(1))?; + seq.serialize_entry("memory_hotplug", &METRICS)?; + seq.end() +} + +#[derive(Debug, Serialize)] +pub(super) struct VirtioMemDeviceMetrics { + /// Number of device activation failures + pub activate_fails: SharedIncMetric, + /// Number of queue event handling failures + pub queue_event_fails: SharedIncMetric, + /// Number of queue events handled + pub queue_event_count: SharedIncMetric, +} + +impl VirtioMemDeviceMetrics { + /// Const default construction. + const fn new() -> Self { + Self { + activate_fails: SharedIncMetric::new(), + queue_event_fails: SharedIncMetric::new(), + queue_event_count: SharedIncMetric::new(), + } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::logger::IncMetric; + + #[test] + fn test_memory_hotplug_metrics() { + let mem_metrics: VirtioMemDeviceMetrics = VirtioMemDeviceMetrics::new(); + let mem_metrics_local: String = serde_json::to_string(&mem_metrics).unwrap(); + // the 1st serialize flushes the metrics and resets values to 0 so that + // we can compare the values with local metrics. + serde_json::to_string(&METRICS).unwrap(); + let mem_metrics_global: String = serde_json::to_string(&METRICS).unwrap(); + assert_eq!(mem_metrics_local, mem_metrics_global); + mem_metrics.queue_event_count.inc(); + assert_eq!(mem_metrics.queue_event_count.count(), 1); + } +} diff --git a/src/vmm/src/devices/virtio/mem/mod.rs b/src/vmm/src/devices/virtio/mem/mod.rs new file mode 100644 index 00000000000..1c9e98f98a6 --- /dev/null +++ b/src/vmm/src/devices/virtio/mem/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +mod device; +mod event_handler; +pub mod metrics; +pub mod persist; + +use vm_memory::GuestAddress; + +pub use self::device::{VirtioMem, VirtioMemError, VirtioMemStatus}; +use crate::arch::FIRST_ADDR_PAST_64BITS_MMIO; + +pub(crate) const MEM_NUM_QUEUES: usize = 1; + +pub(crate) const MEM_QUEUE: usize = 0; + +pub const VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB: usize = 2; +pub const VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB: usize = 128; +pub const VIRTIO_MEM_GUEST_ADDRESS: GuestAddress = GuestAddress(FIRST_ADDR_PAST_64BITS_MMIO); // 512GiB + +pub const VIRTIO_MEM_DEV_ID: &str = "mem"; diff --git a/src/vmm/src/devices/virtio/mem/persist.rs b/src/vmm/src/devices/virtio/mem/persist.rs new file mode 100644 index 00000000000..e48246de500 --- /dev/null +++ b/src/vmm/src/devices/virtio/mem/persist.rs @@ -0,0 +1,136 @@ +// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Defines the structures needed for saving/restoring virtio-mem devices. + +use std::sync::Arc; + +use serde::{Deserialize, Serialize}; +use vm_memory::Address; + +use crate::Vm; +use crate::devices::virtio::generated::virtio_ids::VIRTIO_ID_MEM; +use crate::devices::virtio::generated::virtio_mem::virtio_mem_config; +use crate::devices::virtio::mem::{ + MEM_NUM_QUEUES, VIRTIO_MEM_GUEST_ADDRESS, VirtioMem, VirtioMemError, +}; +use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState}; +use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE; +use crate::snapshot::Persist; +use crate::vstate::memory::{GuestMemoryMmap, GuestRegionMmap}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VirtioMemState { + pub virtio_state: VirtioDeviceState, + region_size: u64, + block_size: u64, + usable_region_size: u64, + plugged_size: u64, + requested_size: u64, + slot_size: usize, +} + +#[derive(Debug)] +pub struct VirtioMemConstructorArgs { + vm: Arc, +} + +impl VirtioMemConstructorArgs { + pub fn new(vm: Arc) -> Self { + Self { vm } + } +} + +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum VirtioMemPersistError { + /// Create virtio-mem: {0} + CreateVirtioMem(#[from] VirtioMemError), + /// Virtio state: {0} + VirtioState(#[from] VirtioStateError), +} + +impl Persist<'_> for VirtioMem { + type State = VirtioMemState; + type ConstructorArgs = VirtioMemConstructorArgs; + type Error = VirtioMemPersistError; + + fn save(&self) -> Self::State { + VirtioMemState { + virtio_state: VirtioDeviceState::from_device(self), + region_size: self.config.region_size, + block_size: self.config.block_size, + usable_region_size: self.config.usable_region_size, + plugged_size: self.config.plugged_size, + requested_size: self.config.requested_size, + slot_size: self.slot_size, + } + } + + fn restore( + constructor_args: Self::ConstructorArgs, + state: &Self::State, + ) -> Result { + let queues = state.virtio_state.build_queues_checked( + constructor_args.vm.guest_memory(), + VIRTIO_ID_MEM, + MEM_NUM_QUEUES, + FIRECRACKER_MAX_QUEUE_SIZE, + )?; + + let config = virtio_mem_config { + addr: VIRTIO_MEM_GUEST_ADDRESS.raw_value(), + region_size: state.region_size, + block_size: state.block_size, + usable_region_size: state.usable_region_size, + plugged_size: state.plugged_size, + requested_size: state.requested_size, + ..Default::default() + }; + + let mut virtio_mem = + VirtioMem::from_state(constructor_args.vm, queues, config, state.slot_size)?; + virtio_mem.set_avail_features(state.virtio_state.avail_features); + virtio_mem.set_acked_features(state.virtio_state.acked_features); + + Ok(virtio_mem) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::devices::virtio::device::VirtioDevice; + use crate::devices::virtio::mem::device::test_utils::default_virtio_mem; + use crate::vstate::vm::tests::setup_vm_with_memory; + + #[test] + fn test_save_state() { + let dev = default_virtio_mem(); + let state = dev.save(); + + assert_eq!(state.region_size, dev.config.region_size); + assert_eq!(state.block_size, dev.config.block_size); + assert_eq!(state.usable_region_size, dev.config.usable_region_size); + assert_eq!(state.plugged_size, dev.config.plugged_size); + assert_eq!(state.requested_size, dev.config.requested_size); + assert_eq!(state.slot_size, dev.slot_size); + } + + #[test] + fn test_save_restore_state() { + let mut original_dev = default_virtio_mem(); + original_dev.set_acked_features(original_dev.avail_features()); + let state = original_dev.save(); + + // Create a "new" VM for restore + let (_, vm) = setup_vm_with_memory(0x1000); + let vm = Arc::new(vm); + let constructor_args = VirtioMemConstructorArgs::new(vm); + let restored_dev = VirtioMem::restore(constructor_args, &state).unwrap(); + + assert_eq!(original_dev.config, restored_dev.config); + assert_eq!(original_dev.slot_size, restored_dev.slot_size); + assert_eq!(original_dev.avail_features(), restored_dev.avail_features()); + assert_eq!(original_dev.acked_features(), restored_dev.acked_features()); + } +} diff --git a/src/vmm/src/devices/virtio/mod.rs b/src/vmm/src/devices/virtio/mod.rs index 1e9e3541720..e0fc7398144 100644 --- a/src/vmm/src/devices/virtio/mod.rs +++ b/src/vmm/src/devices/virtio/mod.rs @@ -18,6 +18,7 @@ pub mod device; pub mod generated; mod iov_deque; pub mod iovec; +pub mod mem; pub mod net; pub mod persist; pub mod queue; @@ -63,6 +64,8 @@ pub enum ActivateError { TapSetOffload(TapError), /// Error setting pointers in the queue: (0) QueueMemoryError(QueueError), + /// The driver didn't acknowledge a required feature: {0} + RequiredFeatureNotAcked(&'static str), } /// Trait that helps in upcasting an object to Any diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 70fe5405e22..d235c539c83 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -525,23 +525,23 @@ impl Net { net_metrics.tx_malformed_frames.inc(); })?; - if let Some(ns) = mmds_ns { - if ns.is_mmds_frame(headers) { - let mut frame = vec![0u8; frame_iovec.len() as usize - vnet_hdr_len()]; - // Ok to unwrap here, because we are passing a buffer that has the exact size - // of the `IoVecBuffer` minus the VNET headers. - frame_iovec - .read_exact_volatile_at(&mut frame, vnet_hdr_len()) - .unwrap(); - let _ = ns.detour_frame(&frame); - METRICS.mmds.rx_accepted.inc(); + if let Some(ns) = mmds_ns + && ns.is_mmds_frame(headers) + { + let mut frame = vec![0u8; frame_iovec.len() as usize - vnet_hdr_len()]; + // Ok to unwrap here, because we are passing a buffer that has the exact size + // of the `IoVecBuffer` minus the VNET headers. + frame_iovec + .read_exact_volatile_at(&mut frame, vnet_hdr_len()) + .unwrap(); + let _ = ns.detour_frame(&frame); + METRICS.mmds.rx_accepted.inc(); - // MMDS frames are not accounted by the rate limiter. - Self::rate_limiter_replenish_op(rate_limiter, u64::from(frame_iovec.len())); + // MMDS frames are not accounted by the rate limiter. + Self::rate_limiter_replenish_op(rate_limiter, u64::from(frame_iovec.len())); - // MMDS consumed the frame. - return Ok(true); - } + // MMDS consumed the frame. + return Ok(true); } // This frame goes to the TAP. @@ -588,31 +588,30 @@ impl Net { } } - if let Some(ns) = self.mmds_ns.as_mut() { - if let Some(len) = + if let Some(ns) = self.mmds_ns.as_mut() + && let Some(len) = ns.write_next_frame(frame_bytes_from_buf_mut(&mut self.rx_frame_buf)?) - { - let len = len.get(); - METRICS.mmds.tx_frames.inc(); - METRICS.mmds.tx_bytes.add(len as u64); - init_vnet_hdr(&mut self.rx_frame_buf); - self.rx_buffer - .iovec - .write_all_volatile_at(&self.rx_frame_buf[..vnet_hdr_len() + len], 0)?; - // SAFETY: - // * len will never be bigger that u32::MAX because mmds is bound - // by the size of `self.rx_frame_buf` which is MAX_BUFFER_SIZE size. - let len: u32 = (vnet_hdr_len() + len).try_into().unwrap(); - - // SAFETY: - // * We checked that `rx_buffer` includes at least one `DescriptorChain` - // * `rx_frame_buf` has size of `MAX_BUFFER_SIZE` and all `DescriptorChain` objects - // are at least that big. - unsafe { - self.rx_buffer.mark_used(len, &mut self.queues[RX_INDEX]); - } - return Ok(Some(len)); + { + let len = len.get(); + METRICS.mmds.tx_frames.inc(); + METRICS.mmds.tx_bytes.add(len as u64); + init_vnet_hdr(&mut self.rx_frame_buf); + self.rx_buffer + .iovec + .write_all_volatile_at(&self.rx_frame_buf[..vnet_hdr_len() + len], 0)?; + // SAFETY: + // * len will never be bigger that u32::MAX because mmds is bound + // by the size of `self.rx_frame_buf` which is MAX_BUFFER_SIZE size. + let len: u32 = (vnet_hdr_len() + len).try_into().unwrap(); + + // SAFETY: + // * We checked that `rx_buffer` includes at least one `DescriptorChain` + // * `rx_frame_buf` has size of `MAX_BUFFER_SIZE` and all `DescriptorChain` objects are + // at least that big. + unsafe { + self.rx_buffer.mark_used(len, &mut self.queues[RX_INDEX]); } + return Ok(Some(len)); } // SAFETY: diff --git a/src/vmm/src/devices/virtio/net/test_utils.rs b/src/vmm/src/devices/virtio/net/test_utils.rs index 6d7bcf15ced..175b23c5626 100644 --- a/src/vmm/src/devices/virtio/net/test_utils.rs +++ b/src/vmm/src/devices/virtio/net/test_utils.rs @@ -199,7 +199,7 @@ pub fn create_socket() -> File { } // Returns handles to virtio queues creation/activation and manipulation. -pub fn virtqueues(mem: &GuestMemoryMmap) -> (VirtQueue, VirtQueue) { +pub fn virtqueues(mem: &GuestMemoryMmap) -> (VirtQueue<'_>, VirtQueue<'_>) { let rxq = VirtQueue::new(GuestAddress(0), mem, 16); let txq = VirtQueue::new(GuestAddress(0x1000), mem, 16); assert!(rxq.end().0 < txq.start().0); @@ -355,7 +355,7 @@ pub mod test { } } - pub fn net(&mut self) -> MutexGuard { + pub fn net(&mut self) -> MutexGuard<'_, Net> { self.net.lock().unwrap() } diff --git a/src/vmm/src/devices/virtio/test_utils.rs b/src/vmm/src/devices/virtio/test_utils.rs index 861394c1c7d..6f1489dd380 100644 --- a/src/vmm/src/devices/virtio/test_utils.rs +++ b/src/vmm/src/devices/virtio/test_utils.rs @@ -416,7 +416,7 @@ pub(crate) mod test { } /// Get a (locked) reference to the device - pub fn device(&mut self) -> MutexGuard { + pub fn device(&mut self) -> MutexGuard<'_, T> { self.device.lock().unwrap() } diff --git a/src/vmm/src/devices/virtio/transport/mmio.rs b/src/vmm/src/devices/virtio/transport/mmio.rs index d6cb83b87c6..c20928e3c29 100644 --- a/src/vmm/src/devices/virtio/transport/mmio.rs +++ b/src/vmm/src/devices/virtio/transport/mmio.rs @@ -84,7 +84,7 @@ impl MmioTransport { } /// Gets the encapsulated locked VirtioDevice. - pub fn locked_device(&self) -> MutexGuard { + pub fn locked_device(&self) -> MutexGuard<'_, dyn VirtioDevice + 'static> { self.device.lock().expect("Poisoned lock") } diff --git a/src/vmm/src/devices/virtio/vhost_user.rs b/src/vmm/src/devices/virtio/vhost_user.rs index 556a8adafaf..bd1260fad40 100644 --- a/src/vmm/src/devices/virtio/vhost_user.rs +++ b/src/vmm/src/devices/virtio/vhost_user.rs @@ -307,17 +307,16 @@ impl VhostUserHandleImpl { acked_features: u64, acked_protocol_features: u64, ) -> Result<(), VhostUserError> { - if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 { - if let Some(acked_protocol_features) = + if acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() != 0 + && let Some(acked_protocol_features) = VhostUserProtocolFeatures::from_bits(acked_protocol_features) - { - self.vu - .set_protocol_features(acked_protocol_features) - .map_err(VhostUserError::VhostUserSetProtocolFeatures)?; + { + self.vu + .set_protocol_features(acked_protocol_features) + .map_err(VhostUserError::VhostUserSetProtocolFeatures)?; - if acked_protocol_features.contains(VhostUserProtocolFeatures::REPLY_ACK) { - self.vu.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); - } + if acked_protocol_features.contains(VhostUserProtocolFeatures::REPLY_ACK) { + self.vu.set_hdr_flags(VhostUserHeaderFlag::NEED_REPLY); } } @@ -861,22 +860,22 @@ pub(crate) mod tests { queue_index: usize, config_data: &VringConfigData, ) -> Result<(), vhost::Error> { - unsafe { (*self.vrings.get())[queue_index].config = *config_data }; + unsafe { (&mut (*self.vrings.get()))[queue_index].config = *config_data }; Ok(()) } fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<(), vhost::Error> { - unsafe { (*self.vrings.get())[queue_index].base = base }; + unsafe { (&mut (*self.vrings.get()))[queue_index].base = base }; Ok(()) } fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<(), vhost::Error> { - unsafe { (*self.vrings.get())[queue_index].call = fd.as_raw_fd() }; + unsafe { (&mut (*self.vrings.get()))[queue_index].call = fd.as_raw_fd() }; Ok(()) } fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<(), vhost::Error> { - unsafe { (*self.vrings.get())[queue_index].kick = fd.as_raw_fd() }; + unsafe { (&mut (*self.vrings.get()))[queue_index].kick = fd.as_raw_fd() }; Ok(()) } diff --git a/src/vmm/src/devices/virtio/vsock/test_utils.rs b/src/vmm/src/devices/virtio/vsock/test_utils.rs index b38ce070c66..3d4ab704975 100644 --- a/src/vmm/src/devices/virtio/vsock/test_utils.rs +++ b/src/vmm/src/devices/virtio/vsock/test_utils.rs @@ -143,7 +143,7 @@ impl TestContext { } } - pub fn create_event_handler_context(&self) -> EventHandlerContext { + pub fn create_event_handler_context(&self) -> EventHandlerContext<'_> { const QSIZE: u16 = 256; let guest_rxvq = GuestQ::new(GuestAddress(0x0010_0000), &self.mem, QSIZE); diff --git a/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs b/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs index dc94b38fe36..17cc193d120 100644 --- a/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs +++ b/src/vmm/src/devices/virtio/vsock/unix/muxer_killq.rs @@ -104,10 +104,10 @@ impl MuxerKillQ { /// This will succeed and return a connection key, only if the connection at the front of /// the queue has expired. Otherwise, `None` is returned. pub fn pop(&mut self) -> Option { - if let Some(item) = self.q.front() { - if Instant::now() > item.kill_time { - return self.q.pop_front().map(|entry| entry.key); - } + if let Some(item) = self.q.front() + && Instant::now() > item.kill_time + { + return self.q.pop_front().map(|entry| entry.key); } None } diff --git a/src/vmm/src/dumbo/pdu/ipv4.rs b/src/vmm/src/dumbo/pdu/ipv4.rs index fab5b88eb49..e49a1f9a025 100644 --- a/src/vmm/src/dumbo/pdu/ipv4.rs +++ b/src/vmm/src/dumbo/pdu/ipv4.rs @@ -568,7 +568,7 @@ mod tests { // Using a helper function here instead of a closure because it's hard (impossible?) to // specify lifetime bounds for closure arguments. - fn p(buf: &mut [u8]) -> IPv4Packet<&mut [u8]> { + fn p(buf: &mut [u8]) -> IPv4Packet<'_, &mut [u8]> { IPv4Packet::from_bytes_unchecked(buf) } diff --git a/src/vmm/src/dumbo/pdu/tcp.rs b/src/vmm/src/dumbo/pdu/tcp.rs index 2ac01227142..ab46da2367a 100644 --- a/src/vmm/src/dumbo/pdu/tcp.rs +++ b/src/vmm/src/dumbo/pdu/tcp.rs @@ -304,10 +304,10 @@ impl TcpSegment<'_, T> { return Err(TcpError::HeaderLen); } - if let Some((src_addr, dst_addr)) = verify_checksum { - if segment.compute_checksum(src_addr, dst_addr) != 0 { - return Err(TcpError::Checksum); - } + if let Some((src_addr, dst_addr)) = verify_checksum + && segment.compute_checksum(src_addr, dst_addr) != 0 + { + return Err(TcpError::Checksum); } Ok(segment) @@ -739,7 +739,7 @@ mod tests { // Using a helper function here instead of a closure because it's hard (impossible?) to // specify lifetime bounds for closure arguments. - fn p(buf: &mut [u8]) -> TcpSegment<&mut [u8]> { + fn p(buf: &mut [u8]) -> TcpSegment<'_, &mut [u8]> { TcpSegment::from_bytes_unchecked(buf) } diff --git a/src/vmm/src/dumbo/tcp/connection.rs b/src/vmm/src/dumbo/tcp/connection.rs index 016a44477a7..311abf7c3aa 100644 --- a/src/vmm/src/dumbo/tcp/connection.rs +++ b/src/vmm/src/dumbo/tcp/connection.rs @@ -654,13 +654,13 @@ impl Connection { let mut enqueue_ack = if payload_len > 0 { let data_end_seq = seq + wrapping_payload_len; - if let Some(fin_seq) = self.fin_received { - if !seq_at_or_after(fin_seq, data_end_seq) { - // TODO: This is a strange situation, because the other endpoint is sending data - // after it initially closed its half of the connection. We simply ignore the - // segment for now. - return Ok((None, recv_status_flags | RecvStatusFlags::DATA_BEYOND_FIN)); - } + if let Some(fin_seq) = self.fin_received + && !seq_at_or_after(fin_seq, data_end_seq) + { + // TODO: This is a strange situation, because the other endpoint is sending data + // after it initially closed its half of the connection. We simply ignore the + // segment for now. + return Ok((None, recv_status_flags | RecvStatusFlags::DATA_BEYOND_FIN)); } if !seq_at_or_after(self.local_rwnd_edge, data_end_seq) { @@ -890,14 +890,14 @@ impl Connection { return self.write_next_segment(buf, mss_reserved, payload_src, now); } - if let Some(fin_seq) = self.send_fin { - if self.highest_ack_received == fin_seq { - // We're in the relatively unlikely situation where our FIN got lost. - // Simply calling write_control_segment() will retransmit it. - let segment = self.write_control_segment::(buf, mss_reserved)?; - self.rto_start = now; - return Ok(Some(segment)); - } + if let Some(fin_seq) = self.send_fin + && self.highest_ack_received == fin_seq + { + // We're in the relatively unlikely situation where our FIN got lost. + // Simply calling write_control_segment() will retransmit it. + let segment = self.write_control_segment::(buf, mss_reserved)?; + self.rto_start = now; + return Ok(Some(segment)); } // We have to remember this is a retransmission for later. @@ -929,10 +929,10 @@ impl Connection { // Make sure we're not trying to send data past the FIN sequence we previously // announced. - if let Some(fin_seq) = self.send_fin { - if seq_after(actual_end, fin_seq) { - return Err(WriteNextError::DataAfterFin); - } + if let Some(fin_seq) = self.send_fin + && seq_after(actual_end, fin_seq) + { + return Err(WriteNextError::DataAfterFin); } // We only proceed with writing a data segment if the previously computed bounds @@ -960,21 +960,21 @@ impl Connection { let payload_len = segment.inner().payload_len(); let mut first_seq_after = seq_to_send + Wrapping(u32::from(payload_len)); - if let Some(fin_seq) = self.send_fin { - if first_seq_after == fin_seq { - // This segment contains the last bytes of data we're going to send, so - // we should also set the FIN flag. - segment - .inner_mut() - .set_flags_after_ns(tcp_flags | TcpFlags::FIN); - - // The FIN takes up 1 sequence number. - first_seq_after += Wrapping(1); - // The main purpose of knowing we sent at least one FIN is to signal that - // we already added 1 to self.first_not_sent, to account for its sequence - // number. - self.set_flags(ConnStatusFlags::FIN_SENT); - } + if let Some(fin_seq) = self.send_fin + && first_seq_after == fin_seq + { + // This segment contains the last bytes of data we're going to send, so + // we should also set the FIN flag. + segment + .inner_mut() + .set_flags_after_ns(tcp_flags | TcpFlags::FIN); + + // The FIN takes up 1 sequence number. + first_seq_after += Wrapping(1); + // The main purpose of knowing we sent at least one FIN is to signal that + // we already added 1 to self.first_not_sent, to account for its sequence + // number. + self.set_flags(ConnStatusFlags::FIN_SENT); } if rto_triggered || self.first_not_sent == self.highest_ack_received { @@ -1122,7 +1122,7 @@ pub(crate) mod tests { &mut self, c: &mut Connection, payload_src: Option<(&[u8], Wrapping)>, - ) -> Result>, WriteNextError> { + ) -> Result>, WriteNextError> { let src_port = self.src_port; let dst_port = self.dst_port; c.write_next_segment(self.buf.as_mut(), self.mss_reserved, payload_src, self.now) diff --git a/src/vmm/src/dumbo/tcp/handler.rs b/src/vmm/src/dumbo/tcp/handler.rs index d8e903a46b6..1be2bb9360c 100644 --- a/src/vmm/src/dumbo/tcp/handler.rs +++ b/src/vmm/src/dumbo/tcp/handler.rs @@ -315,10 +315,10 @@ impl TcpIPv4Handler { tuple: ConnectionTuple, status: NextSegmentStatus, ) -> bool { - if let Some((_, timeout_tuple)) = self.next_timeout { - if tuple == timeout_tuple { - self.find_next_timeout(); - } + if let Some((_, timeout_tuple)) = self.next_timeout + && tuple == timeout_tuple + { + self.find_next_timeout(); } match status { NextSegmentStatus::Available => { @@ -342,10 +342,10 @@ impl TcpIPv4Handler { self.active_connections.remove(&tuple); self.connections.remove(&tuple); - if let Some((_, timeout_tuple)) = self.next_timeout { - if timeout_tuple == tuple { - self.find_next_timeout(); - } + if let Some((_, timeout_tuple)) = self.next_timeout + && timeout_tuple == tuple + { + self.find_next_timeout(); } } diff --git a/src/vmm/src/lib.rs b/src/vmm/src/lib.rs index c3b2410dfe1..44023b68819 100644 --- a/src/vmm/src/lib.rs +++ b/src/vmm/src/lib.rs @@ -136,6 +136,7 @@ use vstate::vcpu::{self, StartThreadedError, VcpuSendEventError}; use crate::cpu_config::templates::CpuConfiguration; use crate::devices::virtio::balloon::{BALLOON_DEV_ID, Balloon, BalloonConfig, BalloonStats}; use crate::devices::virtio::block::device::Block; +use crate::devices::virtio::mem::{VIRTIO_MEM_DEV_ID, VirtioMem, VirtioMemError, VirtioMemStatus}; use crate::devices::virtio::net::Net; use crate::logger::{METRICS, MetricsError, error, info, warn}; use crate::persist::{MicrovmState, MicrovmStateError, VmInfo}; @@ -246,6 +247,8 @@ pub enum VmmError { VMGenID(#[from] VmGenIdError), /// Failed perform action on device: {0} FindDeviceError(#[from] device_manager::FindDeviceError), + /// Failed to create memory hotplug device: {0} + VirtioMem(#[from] VirtioMemError), } /// Shorthand type for KVM dirty page bitmap. @@ -591,6 +594,13 @@ impl Vmm { .map_err(VmmError::FindDeviceError) } + /// Returns the current state of the memory hotplug device. + pub fn memory_hotplug_status(&self) -> Result { + self.device_manager + .with_virtio_device_with_id(VIRTIO_MEM_DEV_ID, |dev: &mut VirtioMem| dev.status()) + .map_err(VmmError::FindDeviceError) + } + /// Signals Vmm to stop and exit. pub fn stop(&mut self, exit_code: FcExitCode) { // To avoid cycles, all teardown paths take the following route: diff --git a/src/vmm/src/logger/metrics.rs b/src/vmm/src/logger/metrics.rs index d5098cbf748..054320992be 100644 --- a/src/vmm/src/logger/metrics.rs +++ b/src/vmm/src/logger/metrics.rs @@ -74,6 +74,7 @@ use super::FcLineWriter; use crate::devices::legacy; use crate::devices::virtio::balloon::metrics as balloon_metrics; use crate::devices::virtio::block::virtio::metrics as block_metrics; +use crate::devices::virtio::mem::metrics as virtio_mem_metrics; use crate::devices::virtio::net::metrics as net_metrics; use crate::devices::virtio::rng::metrics as entropy_metrics; use crate::devices::virtio::vhost_user_metrics; @@ -365,6 +366,8 @@ pub struct GetRequestsMetrics { pub mmds_count: SharedIncMetric, /// Number of GETs for getting the VMM version. pub vmm_version_count: SharedIncMetric, + /// Number of GETs for getting hotpluggable memory status. + pub hotplug_memory_count: SharedIncMetric, } impl GetRequestsMetrics { /// Const default construction. @@ -374,6 +377,7 @@ impl GetRequestsMetrics { machine_cfg_count: SharedIncMetric::new(), mmds_count: SharedIncMetric::new(), vmm_version_count: SharedIncMetric::new(), + hotplug_memory_count: SharedIncMetric::new(), } } } @@ -425,6 +429,10 @@ pub struct PutRequestsMetrics { pub serial_count: SharedIncMetric, /// Number of failed PUTs to /serial pub serial_fails: SharedIncMetric, + /// Number of PUTs to /hotplug/memory + pub hotplug_memory_count: SharedIncMetric, + /// Number of failed PUTs to /hotplug/memory + pub hotplug_memory_fails: SharedIncMetric, } impl PutRequestsMetrics { /// Const default construction. @@ -452,6 +460,8 @@ impl PutRequestsMetrics { vsock_fails: SharedIncMetric::new(), serial_count: SharedIncMetric::new(), serial_fails: SharedIncMetric::new(), + hotplug_memory_count: SharedIncMetric::new(), + hotplug_memory_fails: SharedIncMetric::new(), } } } @@ -746,7 +756,7 @@ impl LatencyAggregateMetrics { /// 1st for start_time_us = get_time_us() /// 2nd for delta_time_us = get_time_us() - start_time; and metrics.store(delta_time_us) /// we have just `_m = metrics.record_latency_metrics()` - pub fn record_latency_metrics(&self) -> LatencyMetricsRecorder { + pub fn record_latency_metrics(&self) -> LatencyMetricsRecorder<'_> { LatencyMetricsRecorder::new(self) } } @@ -864,6 +874,7 @@ create_serialize_proxy!(BalloonMetricsSerializeProxy, balloon_metrics); create_serialize_proxy!(EntropyMetricsSerializeProxy, entropy_metrics); create_serialize_proxy!(VsockMetricsSerializeProxy, vsock_metrics); create_serialize_proxy!(LegacyDevMetricsSerializeProxy, legacy); +create_serialize_proxy!(MemoryHotplugSerializeProxy, virtio_mem_metrics); /// Structure storing all metrics while enforcing serialization support on them. #[derive(Debug, Default, Serialize)] @@ -914,6 +925,9 @@ pub struct FirecrackerMetrics { #[serde(flatten)] /// Vhost-user device related metrics. pub vhost_user_ser: VhostUserMetricsSerializeProxy, + #[serde(flatten)] + /// Virtio-mem device related metrics (memory hotplugging) + pub memory_hotplug_ser: MemoryHotplugSerializeProxy, } impl FirecrackerMetrics { /// Const default construction. @@ -939,6 +953,7 @@ impl FirecrackerMetrics { vsock_ser: VsockMetricsSerializeProxy {}, entropy_ser: EntropyMetricsSerializeProxy {}, vhost_user_ser: VhostUserMetricsSerializeProxy {}, + memory_hotplug_ser: MemoryHotplugSerializeProxy {}, } } } diff --git a/src/vmm/src/mmds/ns.rs b/src/vmm/src/mmds/ns.rs index 8f9a764a7c1..a31cb7247b9 100644 --- a/src/vmm/src/mmds/ns.rs +++ b/src/vmm/src/mmds/ns.rs @@ -386,7 +386,7 @@ mod tests { eth_unsized.with_payload_len_unchecked(packet_len).len() } - fn next_frame_as_ipv4_packet<'a>(&mut self, buf: &'a mut [u8]) -> IPv4Packet<&'a [u8]> { + fn next_frame_as_ipv4_packet<'a>(&mut self, buf: &'a mut [u8]) -> IPv4Packet<'_, &'a [u8]> { let len = self.write_next_frame(buf).unwrap().get(); let eth = EthernetFrame::from_bytes(&buf[..len]).unwrap(); IPv4Packet::from_bytes(&buf[eth.payload_offset()..len], true).unwrap() diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 911ee5e5c99..22dfb347de7 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -25,6 +25,7 @@ use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{ HugePageConfig, MachineConfig, MachineConfigError, MachineConfigUpdate, }; +use crate::vmm_config::memory_hotplug::{MemoryHotplugConfig, MemoryHotplugConfigError}; use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics}; use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; use crate::vmm_config::net::*; @@ -62,6 +63,8 @@ pub enum ResourcesError { VsockDevice(#[from] VsockConfigError), /// Entropy device error: {0} EntropyDevice(#[from] EntropyDeviceError), + /// Memory hotplug config error: {0} + MemoryHotplugConfig(#[from] MemoryHotplugConfigError), } #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] @@ -89,6 +92,7 @@ pub struct VmmConfig { entropy: Option, #[serde(skip)] serial_config: Option, + memory_hotplug: Option, } /// A data structure that encapsulates the device configurations @@ -109,6 +113,8 @@ pub struct VmResources { pub net_builder: NetBuilder, /// The entropy device builder. pub entropy: EntropyDeviceBuilder, + /// The memory hotplug configuration. + pub memory_hotplug: Option, /// The optional Mmds data store. // This is initialised on demand (if ever used), so that we don't allocate it unless it's // actually used. @@ -202,6 +208,10 @@ impl VmResources { resources.serial_out_path = serial_cfg.serial_out_path; } + if let Some(memory_hotplug_config) = vmm_config.memory_hotplug { + resources.set_memory_hotplug_config(memory_hotplug_config)?; + } + Ok(resources) } @@ -247,6 +257,14 @@ impl VmResources { SharedDeviceType::Entropy(entropy) => { self.entropy.set_device(entropy); } + SharedDeviceType::VirtioMem(mem) => { + let mem = mem.lock().unwrap(); + self.memory_hotplug = Some(MemoryHotplugConfig { + total_size_mib: mem.total_size_mib(), + block_size_mib: mem.block_size_mib(), + slot_size_mib: mem.slot_size_mib(), + }) + } } Ok(()) @@ -389,6 +407,16 @@ impl VmResources { self.entropy.insert(body) } + /// Sets the memory hotplug configuration. + pub fn set_memory_hotplug_config( + &mut self, + config: MemoryHotplugConfig, + ) -> Result<(), MemoryHotplugConfigError> { + config.validate()?; + self.memory_hotplug = Some(config); + Ok(()) + } + /// Setter for mmds config. pub fn set_mmds_config( &mut self, @@ -451,7 +479,7 @@ impl VmResources { // Create `MmdsNetworkStack` and configure the IPv4 address for // existing built network devices whose names are defined in the // network interface ID list. - for net_device in self.net_builder.iter_mut() { + for net_device in self.net_builder.iter() { let mut net_device_lock = net_device.lock().expect("Poisoned lock"); if network_interfaces.contains(net_device_lock.id()) { net_device_lock.configure_mmds_network_stack(ipv4_addr, mmds.clone()); @@ -517,6 +545,7 @@ impl From<&VmResources> for VmmConfig { entropy: resources.entropy.config(), // serial_config is marked serde(skip) so that it doesnt end up in snapshots. serial_config: None, + memory_hotplug: resources.memory_hotplug.clone(), } } } @@ -629,6 +658,7 @@ mod tests { entropy: Default::default(), pci_enabled: false, serial_out_path: None, + memory_hotplug: Default::default(), } } diff --git a/src/vmm/src/rpc_interface.rs b/src/vmm/src/rpc_interface.rs index 8f2ff6b7740..fe3e9c296e7 100644 --- a/src/vmm/src/rpc_interface.rs +++ b/src/vmm/src/rpc_interface.rs @@ -14,6 +14,7 @@ use super::{Vmm, VmmError}; use crate::EventManager; use crate::builder::StartMicrovmError; use crate::cpu_config::templates::{CustomCpuTemplate, GuestConfigError}; +use crate::devices::virtio::mem::VirtioMemStatus; use crate::logger::{LoggerConfig, info, warn, *}; use crate::mmds::data_store::{self, Mmds}; use crate::persist::{CreateSnapshotError, RestoreFromSnapshotError, VmInfo}; @@ -28,6 +29,7 @@ use crate::vmm_config::drive::{BlockDeviceConfig, BlockDeviceUpdateConfig, Drive use crate::vmm_config::entropy::{EntropyDeviceConfig, EntropyDeviceError}; use crate::vmm_config::instance_info::InstanceInfo; use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError, MachineConfigUpdate}; +use crate::vmm_config::memory_hotplug::{MemoryHotplugConfig, MemoryHotplugConfigError}; use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError}; use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError}; use crate::vmm_config::net::{ @@ -106,6 +108,11 @@ pub enum VmmAction { /// Set the entropy device using `EntropyDeviceConfig` as input. This action can only be called /// before the microVM has booted. SetEntropyDevice(EntropyDeviceConfig), + /// Get the memory hotplug device configuration and status. + GetMemoryHotplugStatus, + /// Set the memory hotplug device using `MemoryHotplugConfig` as input. This action can only be + /// called before the microVM has booted. + SetMemoryHotplugDevice(MemoryHotplugConfig), /// Launch the microVM. This action can only be called before the microVM has booted. StartMicroVm, /// Send CTRL+ALT+DEL to the microVM, using the i8042 keyboard function. If an AT-keyboard @@ -143,6 +150,8 @@ pub enum VmmActionError { DriveConfig(#[from] DriveError), /// Entropy device error: {0} EntropyDevice(#[from] EntropyDeviceError), + /// Memory hotplug config error: {0} + MemoryHotplugConfig(#[from] MemoryHotplugConfigError), /// Internal VMM error: {0} InternalVmm(#[from] VmmError), /// Load snapshot error: {0} @@ -196,6 +205,8 @@ pub enum VmmData { InstanceInformation(InstanceInfo), /// The microVM version. VmmVersion(String), + /// The status of the memory hotplug device. + VirtioMemStatus(VirtioMemStatus), } /// Trait used for deduplicating the MMDS request handling across the two ApiControllers. @@ -447,12 +458,14 @@ impl<'a> PrebootApiController<'a> { StartMicroVm => self.start_microvm(), UpdateMachineConfiguration(config) => self.update_machine_config(config), SetEntropyDevice(config) => self.set_entropy_device(config), + SetMemoryHotplugDevice(config) => self.set_memory_hotplug_device(config), // Operations not allowed pre-boot. CreateSnapshot(_) | FlushMetrics | Pause | Resume | GetBalloonStats + | GetMemoryHotplugStatus | UpdateBalloon(_) | UpdateBalloonStatistics(_) | UpdateBlockDevice(_) @@ -546,6 +559,15 @@ impl<'a> PrebootApiController<'a> { Ok(VmmData::Empty) } + fn set_memory_hotplug_device( + &mut self, + cfg: MemoryHotplugConfig, + ) -> Result { + self.boot_path = true; + self.vm_resources.set_memory_hotplug_config(cfg)?; + Ok(VmmData::Empty) + } + // On success, this command will end the pre-boot stage and this controller // will be replaced by a runtime controller. fn start_microvm(&mut self) -> Result { @@ -648,6 +670,13 @@ impl RuntimeApiController { .map(VmmData::BalloonStats) .map_err(VmmActionError::InternalVmm), GetFullVmConfig => Ok(VmmData::FullVmConfig((&self.vm_resources).into())), + GetMemoryHotplugStatus => self + .vmm + .lock() + .expect("Poisoned lock") + .memory_hotplug_status() + .map(VmmData::VirtioMemStatus) + .map_err(VmmActionError::InternalVmm), GetMMDS => self.get_mmds(), GetVmMachineConfig => Ok(VmmData::MachineConfiguration( self.vm_resources.machine_config.clone(), @@ -694,6 +723,7 @@ impl RuntimeApiController { | SetVsockDevice(_) | SetMmdsConfiguration(_) | SetEntropyDevice(_) + | SetMemoryHotplugDevice(_) | StartMicroVm | UpdateMachineConfiguration(_) => Err(VmmActionError::OperationNotSupportedPostBoot), } @@ -1272,5 +1302,8 @@ mod tests { check_unsupported(runtime_request(VmmAction::SetEntropyDevice( EntropyDeviceConfig::default(), ))); + check_unsupported(runtime_request(VmmAction::SetMemoryHotplugDevice( + MemoryHotplugConfig::default(), + ))); } } diff --git a/src/vmm/src/utils/mod.rs b/src/vmm/src/utils/mod.rs index 430f9fe9a71..f7f7833aa5e 100644 --- a/src/vmm/src/utils/mod.rs +++ b/src/vmm/src/utils/mod.rs @@ -54,6 +54,11 @@ pub const fn mib_to_bytes(mib: usize) -> usize { mib << MIB_TO_BYTES_SHIFT } +/// Converts Bytes to MiB, truncating any remainder +pub const fn bytes_to_mib(bytes: usize) -> usize { + bytes >> MIB_TO_BYTES_SHIFT +} + /// Align address up to the aligment. pub const fn align_up(addr: u64, align: u64) -> u64 { debug_assert!(align != 0); diff --git a/src/vmm/src/vmm_config/memory_hotplug.rs b/src/vmm/src/vmm_config/memory_hotplug.rs new file mode 100644 index 00000000000..d09141c1b66 --- /dev/null +++ b/src/vmm/src/vmm_config/memory_hotplug.rs @@ -0,0 +1,219 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Serialize}; + +use crate::devices::virtio::mem::{ + VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB, VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB, +}; + +/// Errors associated with memory hotplug configuration. +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum MemoryHotplugConfigError { + /// Block size must not be lower than {0} MiB + BlockSizeTooSmall(usize), + /// Block size must be a power of 2 + BlockSizeNotPowerOfTwo, + /// Slot size must not be lower than {0} MiB + SlotSizeTooSmall(usize), + /// Slot size must be a multiple of block size ({0} MiB) + SlotSizeNotMultipleOfBlockSize(usize), + /// Total size must not be lower than slot size ({0} MiB) + TotalSizeTooSmall(usize), + /// Total size must be a multiple of slot size ({0} MiB) + TotalSizeNotMultipleOfSlotSize(usize), +} + +fn default_block_size_mib() -> usize { + VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB +} + +fn default_slot_size_mib() -> usize { + VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB +} + +/// Configuration for memory hotplug device. +#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct MemoryHotplugConfig { + /// Total memory size in MiB that can be hotplugged. + pub total_size_mib: usize, + /// Block size in MiB. A block is the smallest unit the guest can hot(un)plug + #[serde(default = "default_block_size_mib")] + pub block_size_mib: usize, + /// Slot size in MiB. A slot is the smallest unit the host can (de)attach memory + #[serde(default = "default_slot_size_mib")] + pub slot_size_mib: usize, +} + +impl MemoryHotplugConfig { + /// Validates the configuration. + pub fn validate(&self) -> Result<(), MemoryHotplugConfigError> { + let min_block_size_mib = VIRTIO_MEM_DEFAULT_BLOCK_SIZE_MIB; + if self.block_size_mib < min_block_size_mib { + return Err(MemoryHotplugConfigError::BlockSizeTooSmall( + min_block_size_mib, + )); + } + if !self.block_size_mib.is_power_of_two() { + return Err(MemoryHotplugConfigError::BlockSizeNotPowerOfTwo); + } + + let min_slot_size_mib = VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB; + if self.slot_size_mib < min_slot_size_mib { + return Err(MemoryHotplugConfigError::SlotSizeTooSmall( + min_slot_size_mib, + )); + } + if !self.slot_size_mib.is_multiple_of(self.block_size_mib) { + return Err(MemoryHotplugConfigError::SlotSizeNotMultipleOfBlockSize( + self.block_size_mib, + )); + } + + if self.total_size_mib < self.slot_size_mib { + return Err(MemoryHotplugConfigError::TotalSizeTooSmall( + self.slot_size_mib, + )); + } + if !self.total_size_mib.is_multiple_of(self.slot_size_mib) { + return Err(MemoryHotplugConfigError::TotalSizeNotMultipleOfSlotSize( + self.slot_size_mib, + )); + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use serde_json; + + use super::*; + + #[test] + fn test_valid_config() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 128, + }; + config.validate().unwrap(); + } + + #[test] + fn test_block_size_too_small() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 1, + slot_size_mib: 128, + }; + match config.validate() { + Err(MemoryHotplugConfigError::BlockSizeTooSmall(min)) => assert_eq!(min, 2), + _ => panic!("Expected InvalidBlockSizeTooSmall error"), + } + } + + #[test] + fn test_block_size_not_power_of_two() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 3, + slot_size_mib: 128, + }; + match config.validate() { + Err(MemoryHotplugConfigError::BlockSizeNotPowerOfTwo) => {} + _ => panic!("Expected InvalidBlockSizePowerOfTwo error"), + } + } + + #[test] + fn test_slot_size_too_small() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 1, + }; + match config.validate() { + Err(MemoryHotplugConfigError::SlotSizeTooSmall(min)) => assert_eq!(min, 128), + _ => panic!("Expected InvalidSlotSizeTooSmall error"), + } + } + + #[test] + fn test_slot_size_not_multiple_of_block_size() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 4, + slot_size_mib: 130, + }; + match config.validate() { + Err(MemoryHotplugConfigError::SlotSizeNotMultipleOfBlockSize(block_size)) => { + assert_eq!(block_size, 4) + } + _ => panic!("Expected InvalidSlotSizeMultiple error"), + } + } + + #[test] + fn test_total_size_too_small() { + let config = MemoryHotplugConfig { + total_size_mib: 64, + block_size_mib: 2, + slot_size_mib: 128, + }; + match config.validate() { + Err(MemoryHotplugConfigError::TotalSizeTooSmall(slot_size)) => { + assert_eq!(slot_size, 128) + } + _ => panic!("Expected InvalidTotalSizeTooSmall error"), + } + } + + #[test] + fn test_total_size_not_multiple_of_slot_size() { + let config = MemoryHotplugConfig { + total_size_mib: 1000, + block_size_mib: 2, + slot_size_mib: 128, + }; + match config.validate() { + Err(MemoryHotplugConfigError::TotalSizeNotMultipleOfSlotSize(slot_size)) => { + assert_eq!(slot_size, 128) + } + _ => panic!("Expected InvalidTotalSizeMultiple error"), + } + } + + #[test] + fn test_defaults() { + assert_eq!(default_block_size_mib(), 2); + assert_eq!(default_slot_size_mib(), 128); + + let json = r#"{ + "total_size_mib": 1024 + }"#; + let deserialized: MemoryHotplugConfig = serde_json::from_str(json).unwrap(); + assert_eq!( + deserialized, + MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 2, + slot_size_mib: 128, + } + ); + } + + #[test] + fn test_serde() { + let config = MemoryHotplugConfig { + total_size_mib: 1024, + block_size_mib: 4, + slot_size_mib: 256, + }; + let json = serde_json::to_string(&config).unwrap(); + let deserialized: MemoryHotplugConfig = serde_json::from_str(&json).unwrap(); + assert_eq!(config, deserialized); + } +} diff --git a/src/vmm/src/vmm_config/mod.rs b/src/vmm/src/vmm_config/mod.rs index 0e244ad4328..8c306f7b9bf 100644 --- a/src/vmm/src/vmm_config/mod.rs +++ b/src/vmm/src/vmm_config/mod.rs @@ -24,6 +24,8 @@ pub mod entropy; pub mod instance_info; /// Wrapper for configuring the memory and CPU of the microVM. pub mod machine_config; +/// Wrapper for configuring memory hotplug. +pub mod memory_hotplug; /// Wrapper for configuring the metrics. pub mod metrics; /// Wrapper for configuring the MMDS. diff --git a/src/vmm/src/vmm_config/net.rs b/src/vmm/src/vmm_config/net.rs index f1413368090..81a2db49f33 100644 --- a/src/vmm/src/vmm_config/net.rs +++ b/src/vmm/src/vmm_config/net.rs @@ -89,15 +89,10 @@ impl NetBuilder { } /// Returns a immutable iterator over the network devices. - pub fn iter(&self) -> ::std::slice::Iter>> { + pub fn iter(&self) -> ::std::slice::Iter<'_, Arc>> { self.net_devices.iter() } - /// Returns a mutable iterator over the network devices. - pub fn iter_mut(&mut self) -> ::std::slice::IterMut>> { - self.net_devices.iter_mut() - } - /// Adds an existing network device in the builder. pub fn add_device(&mut self, device: Arc>) { self.net_devices.push(device); diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs index 31eb8d1ccd1..deef6710b90 100644 --- a/src/vmm/src/vstate/vm.rs +++ b/src/vmm/src/vstate/vm.rs @@ -410,7 +410,7 @@ impl Vm { } /// Gets a mutable reference to this [`Vm`]'s [`ResourceAllocator`] object - pub fn resource_allocator(&self) -> MutexGuard { + pub fn resource_allocator(&self) -> MutexGuard<'_, ResourceAllocator> { self.common .resource_allocator .lock() diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json deleted file mode 100644 index ce346c88a28..00000000000 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json +++ /dev/null @@ -1,1227 +0,0 @@ -{ - "firecracker_version": "1.13.0-dev", - "kernel_version": "5.10.238-234.956.amzn2.x86_64", - "microcode_version": "0x2007006", - "bios_version": "1.0", - "bios_revision": "4.14", - "guest_cpu_config": { - "kvm_capabilities": [], - "cpuid_modifiers": [ - { - "leaf": "0x0", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000010110" - }, - { - "register": "ebx", - "bitmap": "0b01110101011011100110010101000111" - }, - { - "register": "ecx", - "bitmap": "0b01101100011001010111010001101110" - }, - { - "register": "edx", - "bitmap": "0b01001001011001010110111001101001" - } - ] - }, - { - "leaf": "0x1", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000001010000011001010100" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000010000100000000000" - }, - { - "register": "ecx", - "bitmap": "0b11110111111110100011001000000011" - }, - { - "register": "edx", - "bitmap": "0b00001111100010111111101111111111" - } - ] - }, - { - "leaf": "0x2", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01110110000000110110001100000001" - }, - { - "register": "ebx", - "bitmap": "0b00000000111100001011010111111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000110000110000000000000000" - } - ] - }, - { - "leaf": "0x3", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100100001" - }, - { - "register": "ebx", - "bitmap": "0b00000001110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100100010" - }, - { - "register": "ebx", - "bitmap": "0b00000001110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x2", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000101000011" - }, - { - "register": "ebx", - "bitmap": "0b00000011110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000001111111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x3", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000101100011" - }, - { - "register": "ebx", - "bitmap": "0b00000010100000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000001000111111111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000100" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x4", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x5", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x6", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000100" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x7", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b11010001100111110110111111111011" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000001100" - }, - { - "register": "edx", - "bitmap": "0b10101100000000000000010000000000" - } - ] - }, - { - "leaf": "0x8", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x9", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xa", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xb", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000001" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000100000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xb", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000101" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000001" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000001000000001" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xc", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000001011111111" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000101010001000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000001111" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x2", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x3", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001111000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x4", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x5", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x6", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000001000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x7", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000010000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000011010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x9", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000001000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000101010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xe", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xf", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x10", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x11", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x12", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x13", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x14", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x15", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x16", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x40000000", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01000000000000000000000000000001" - }, - { - "register": "ebx", - "bitmap": "0b01001011010011010101011001001011" - }, - { - "register": "ecx", - "bitmap": "0b01010110010010110100110101010110" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000001001101" - } - ] - }, - { - "leaf": "0x40000001", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000001000000000111111011111011" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000000", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b10000000000000000000000000001000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000001", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000100100001" - }, - { - "register": "edx", - "bitmap": "0b00101100000100000000100000000000" - } - ] - }, - { - "leaf": "0x80000002", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01100101011101000110111001001001" - }, - { - "register": "ebx", - "bitmap": "0b00101001010100100010100001101100" - }, - { - "register": "ecx", - "bitmap": "0b01101111011001010101100000100000" - }, - { - "register": "edx", - "bitmap": "0b00101001010100100010100001101110" - } - ] - }, - { - "leaf": "0x80000003", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01101111011100100101000000100000" - }, - { - "register": "ebx", - "bitmap": "0b01110011011100110110010101100011" - }, - { - "register": "ecx", - "bitmap": "0b01000000001000000111001001101111" - }, - { - "register": "edx", - "bitmap": "0b00110000001011100011001100100000" - } - ] - }, - { - "leaf": "0x80000004", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01111010010010000100011100110000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000005", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000006", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000001000000000110000001000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000007", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000100000000" - } - ] - }, - { - "leaf": "0x80000008", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000011000000101110" - }, - { - "register": "ebx", - "bitmap": "0b00000001000000001101000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - } - ], - "msr_modifiers": [ - { - "addr": "0x11", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x12", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x34", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x3a", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x3b", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x48", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x8b", - "bitmap": "0b0000000000000000000000000000000100000000000000000000000000000000" - }, - { - "addr": "0x9e", - "bitmap": "0b0000000000000000000000000000000000000000000000110000000000000000" - }, - { - "addr": "0xce", - "bitmap": "0b0000000000000000000000000000000010000000000000000000000000000000" - }, - { - "addr": "0x10a", - "bitmap": "0b0100000000000000000000000000000000001100000000000000000001001100" - }, - { - "addr": "0x140", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x174", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x175", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x176", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x1a0", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "addr": "0x1fc", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x277", - "bitmap": "0b0000000000000111000001000000011000000000000001110000010000000110" - }, - { - "addr": "0xd90", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d00", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d01", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d02", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d03", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d04", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d05", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "addr": "0x4b564d06", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d07", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000081", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000082", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000083", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000084", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000102", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000103", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0010015", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - } - ] - } -} \ No newline at end of file diff --git a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_6.1host.json b/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_6.1host.json deleted file mode 100644 index 87c941f3a04..00000000000 --- a/tests/data/cpu_template_helper/fingerprint_INTEL_SKYLAKE_6.1host.json +++ /dev/null @@ -1,1227 +0,0 @@ -{ - "firecracker_version": "1.13.0-dev", - "kernel_version": "6.1.141-165.249.amzn2023.x86_64", - "microcode_version": "0x2007006", - "bios_version": "1.0", - "bios_revision": "4.14", - "guest_cpu_config": { - "kvm_capabilities": [], - "cpuid_modifiers": [ - { - "leaf": "0x0", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000010110" - }, - { - "register": "ebx", - "bitmap": "0b01110101011011100110010101000111" - }, - { - "register": "ecx", - "bitmap": "0b01101100011001010111010001101110" - }, - { - "register": "edx", - "bitmap": "0b01001001011001010110111001101001" - } - ] - }, - { - "leaf": "0x1", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000001010000011001010100" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000010000100000000000" - }, - { - "register": "ecx", - "bitmap": "0b11110111111110100011001000000011" - }, - { - "register": "edx", - "bitmap": "0b00001111100010111111101111111111" - } - ] - }, - { - "leaf": "0x2", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01110110000000110110001100000001" - }, - { - "register": "ebx", - "bitmap": "0b00000000111100001011010111111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000110000110000000000000000" - } - ] - }, - { - "leaf": "0x3", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100100001" - }, - { - "register": "ebx", - "bitmap": "0b00000001110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100100010" - }, - { - "register": "ebx", - "bitmap": "0b00000001110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x2", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000101000011" - }, - { - "register": "ebx", - "bitmap": "0b00000011110000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000001111111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x3", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000101100011" - }, - { - "register": "ebx", - "bitmap": "0b00000010100000000000000000111111" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000001000111111111111" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000100" - } - ] - }, - { - "leaf": "0x4", - "subleaf": "0x4", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x5", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x6", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000100" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x7", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b11010001100111110110111111111011" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000001100" - }, - { - "register": "edx", - "bitmap": "0b10101100000000000000010000000000" - } - ] - }, - { - "leaf": "0x8", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x9", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xa", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xb", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000001" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000100000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xb", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000101" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000001" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000001000000001" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xc", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000001011111111" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000101010001000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x1", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000001111" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x2", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000100000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x3", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000001111000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x4", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x5", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000001000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010001000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x6", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000001000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000010010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x7", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000010000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000011010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xd", - "subleaf": "0x9", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000001000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000101010000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xe", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0xf", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x10", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x11", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x12", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x13", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x14", - "subleaf": "0x0", - "flags": 1, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x15", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x16", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x40000000", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01000000000000000000000000000001" - }, - { - "register": "ebx", - "bitmap": "0b01001011010011010101011001001011" - }, - { - "register": "ecx", - "bitmap": "0b01010110010010110100110101010110" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000001001101" - } - ] - }, - { - "leaf": "0x40000001", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000001000000000111111011111011" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000000", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b10000000000000000000000000001000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000001", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000100100001" - }, - { - "register": "edx", - "bitmap": "0b00101100000100000000100000000000" - } - ] - }, - { - "leaf": "0x80000002", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01100101011101000110111001001001" - }, - { - "register": "ebx", - "bitmap": "0b00101001010100100010100001101100" - }, - { - "register": "ecx", - "bitmap": "0b01101111011001010101100000100000" - }, - { - "register": "edx", - "bitmap": "0b00101001010100100010100001101110" - } - ] - }, - { - "leaf": "0x80000003", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01101111011100100101000000100000" - }, - { - "register": "ebx", - "bitmap": "0b01110011011100110110010101100011" - }, - { - "register": "ecx", - "bitmap": "0b01000000001000000111001001101111" - }, - { - "register": "edx", - "bitmap": "0b00110000001011100011001100100000" - } - ] - }, - { - "leaf": "0x80000004", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b01111010010010000100011100110000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000005", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000006", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000001000000000110000001000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - }, - { - "leaf": "0x80000007", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ebx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000100000000" - } - ] - }, - { - "leaf": "0x80000008", - "subleaf": "0x0", - "flags": 0, - "modifiers": [ - { - "register": "eax", - "bitmap": "0b00000000000000000011000000101110" - }, - { - "register": "ebx", - "bitmap": "0b00000001000000001101000000000000" - }, - { - "register": "ecx", - "bitmap": "0b00000000000000000000000000000000" - }, - { - "register": "edx", - "bitmap": "0b00000000000000000000000000000000" - } - ] - } - ], - "msr_modifiers": [ - { - "addr": "0x11", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x12", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x34", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x3a", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x3b", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x48", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x8b", - "bitmap": "0b0000000000000000000000000000000100000000000000000000000000000000" - }, - { - "addr": "0x9e", - "bitmap": "0b0000000000000000000000000000000000000000000000110000000000000000" - }, - { - "addr": "0xce", - "bitmap": "0b0000000000000000000000000000000010000000000000000000000000000000" - }, - { - "addr": "0x10a", - "bitmap": "0b0100000000000000000000000000000000001100000000000000000001001100" - }, - { - "addr": "0x140", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x174", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x175", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x176", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x1a0", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "addr": "0x1fc", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x277", - "bitmap": "0b0000000000000111000001000000011000000000000001110000010000000110" - }, - { - "addr": "0xd90", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d00", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d01", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d02", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d03", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d04", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d05", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "addr": "0x4b564d06", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0x4b564d07", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000081", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000082", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000083", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000084", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000102", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0000103", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "addr": "0xc0010015", - "bitmap": "0b0000000000000000000000000000000000000000000000000000000000000000" - } - ] - } -} \ No newline at end of file diff --git a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_5.10guest.csv b/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_5.10guest.csv deleted file mode 100644 index c901b2c8483..00000000000 --- a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_5.10guest.csv +++ /dev/null @@ -1,508 +0,0 @@ -MSR_ADDR,VALUE -0x0,0x0 -0x1,0x0 -0x10,0xff34f950 -0x11,0x2748008 -0x12,0x2749001 -0x17,0x0 -0x1b,0xfee00d00 -0x2a,0x0 -0x2c,0x1000000 -0x34,0x0 -0x3a,0x1 -0x3b,0x0 -0x48,0x1 -0x8b,0x100000000 -0xc1,0x0 -0xc2,0x0 -0xcd,0x3 -0xce,0x80000000 -0xfe,0x508 -0x10a,0xc080c4c -0x11e,0xbe702111 -0x140,0x0 -0x174,0x10 -0x175,0xfffffe0000003000 -0x176,0xffffffff81801450 -0x179,0x20 -0x17a,0x0 -0x186,0x0 -0x187,0x0 -0x198,0x400000003e8 -0x199,0x0 -0x1a0,0x1 -0x1d9,0x0 -0x1db,0x0 -0x1dc,0x0 -0x1dd,0x0 -0x1de,0x0 -0x1fc,0x0 -0x200,0x0 -0x201,0x0 -0x202,0x0 -0x203,0x0 -0x204,0x0 -0x205,0x0 -0x206,0x0 -0x207,0x0 -0x208,0x0 -0x209,0x0 -0x20a,0x0 -0x20b,0x0 -0x20c,0x0 -0x20d,0x0 -0x20e,0x0 -0x20f,0x0 -0x250,0x0 -0x258,0x0 -0x259,0x0 -0x268,0x0 -0x269,0x0 -0x26a,0x0 -0x26b,0x0 -0x26c,0x0 -0x26d,0x0 -0x26e,0x0 -0x26f,0x0 -0x277,0x7040600070406 -0x2ff,0x0 -0x400,0x0 -0x401,0x0 -0x402,0x0 -0x403,0x0 -0x404,0x0 -0x405,0x0 -0x406,0x0 -0x407,0x0 -0x408,0x0 -0x409,0x0 -0x40a,0x0 -0x40b,0x0 -0x40c,0x0 -0x40d,0x0 -0x40e,0x0 -0x40f,0x0 -0x410,0x0 -0x411,0x0 -0x412,0x0 -0x413,0x0 -0x414,0x0 -0x415,0x0 -0x416,0x0 -0x417,0x0 -0x418,0x0 -0x419,0x0 -0x41a,0x0 -0x41b,0x0 -0x41c,0x0 -0x41d,0x0 -0x41e,0x0 -0x41f,0x0 -0x420,0x0 -0x421,0x0 -0x422,0x0 -0x423,0x0 -0x424,0x0 -0x425,0x0 -0x426,0x0 -0x427,0x0 -0x428,0x0 -0x429,0x0 -0x42a,0x0 -0x42b,0x0 -0x42c,0x0 -0x42d,0x0 -0x42e,0x0 -0x42f,0x0 -0x430,0x0 -0x431,0x0 -0x432,0x0 -0x433,0x0 -0x434,0x0 -0x435,0x0 -0x436,0x0 -0x437,0x0 -0x438,0x0 -0x439,0x0 -0x43a,0x0 -0x43b,0x0 -0x43c,0x0 -0x43d,0x0 -0x43e,0x0 -0x43f,0x0 -0x440,0x0 -0x441,0x0 -0x442,0x0 -0x443,0x0 -0x444,0x0 -0x445,0x0 -0x446,0x0 -0x447,0x0 -0x448,0x0 -0x449,0x0 -0x44a,0x0 -0x44b,0x0 -0x44c,0x0 -0x44d,0x0 -0x44e,0x0 -0x44f,0x0 -0x450,0x0 -0x451,0x0 -0x452,0x0 -0x453,0x0 -0x454,0x0 -0x455,0x0 -0x456,0x0 -0x457,0x0 -0x458,0x0 -0x459,0x0 -0x45a,0x0 -0x45b,0x0 -0x45c,0x0 -0x45d,0x0 -0x45e,0x0 -0x45f,0x0 -0x460,0x0 -0x461,0x0 -0x462,0x0 -0x463,0x0 -0x464,0x0 -0x465,0x0 -0x466,0x0 -0x467,0x0 -0x468,0x0 -0x469,0x0 -0x46a,0x0 -0x46b,0x0 -0x46c,0x0 -0x46d,0x0 -0x46e,0x0 -0x46f,0x0 -0x470,0x0 -0x471,0x0 -0x472,0x0 -0x473,0x0 -0x474,0x0 -0x475,0x0 -0x476,0x0 -0x477,0x0 -0x478,0x0 -0x479,0x0 -0x47a,0x0 -0x47b,0x0 -0x47c,0x0 -0x47d,0x0 -0x47e,0x0 -0x47f,0x0 -0x606,0x0 -0x611,0x0 -0x619,0x0 -0x639,0x0 -0x641,0x0 -0x6e0,0x2d1e43b52 -0x800,0x0 -0x801,0x0 -0x802,0x0 -0x803,0x50014 -0x804,0x0 -0x805,0x0 -0x806,0x0 -0x807,0x0 -0x808,0x10 -0x809,0x0 -0x80a,0x10 -0x80b,0x0 -0x80c,0x0 -0x80d,0x1 -0x80e,0xffffffff -0x80f,0x1ff -0x810,0x0 -0x811,0x0 -0x812,0x0 -0x813,0x0 -0x814,0x0 -0x815,0x0 -0x816,0x0 -0x817,0x0 -0x818,0x0 -0x819,0x0 -0x81a,0x0 -0x81b,0x0 -0x81c,0x0 -0x81d,0x0 -0x81e,0x0 -0x81f,0x0 -0x820,0x0 -0x821,0x0 -0x822,0x0 -0x823,0x0 -0x824,0x0 -0x825,0x0 -0x826,0x0 -0x827,0x0 -0x828,0x0 -0x829,0x0 -0x82a,0x0 -0x82b,0x0 -0x82c,0x0 -0x82d,0x0 -0x82e,0x0 -0x82f,0x0 -0x830,0x0 -0x831,0x0 -0x832,0x400ec -0x833,0x10000 -0x834,0x10000 -0x835,0x10700 -0x836,0x400 -0x837,0xfe -0x838,0x0 -0x839,0x0 -0x83a,0x0 -0x83b,0x0 -0x83c,0x0 -0x83d,0x0 -0x83e,0x0 -0x83f,0x0 -0x840,0x0 -0x841,0x0 -0x842,0x0 -0x843,0x0 -0x844,0x0 -0x845,0x0 -0x846,0x0 -0x847,0x0 -0x848,0x0 -0x849,0x0 -0x84a,0x0 -0x84b,0x0 -0x84c,0x0 -0x84d,0x0 -0x84e,0x0 -0x84f,0x0 -0x850,0x0 -0x851,0x0 -0x852,0x0 -0x853,0x0 -0x854,0x0 -0x855,0x0 -0x856,0x0 -0x857,0x0 -0x858,0x0 -0x859,0x0 -0x85a,0x0 -0x85b,0x0 -0x85c,0x0 -0x85d,0x0 -0x85e,0x0 -0x85f,0x0 -0x860,0x0 -0x861,0x0 -0x862,0x0 -0x863,0x0 -0x864,0x0 -0x865,0x0 -0x866,0x0 -0x867,0x0 -0x868,0x0 -0x869,0x0 -0x86a,0x0 -0x86b,0x0 -0x86c,0x0 -0x86d,0x0 -0x86e,0x0 -0x86f,0x0 -0x870,0x0 -0x871,0x0 -0x872,0x0 -0x873,0x0 -0x874,0x0 -0x875,0x0 -0x876,0x0 -0x877,0x0 -0x878,0x0 -0x879,0x0 -0x87a,0x0 -0x87b,0x0 -0x87c,0x0 -0x87d,0x0 -0x87e,0x0 -0x87f,0x0 -0x880,0x0 -0x881,0x0 -0x882,0x0 -0x883,0x0 -0x884,0x0 -0x885,0x0 -0x886,0x0 -0x887,0x0 -0x888,0x0 -0x889,0x0 -0x88a,0x0 -0x88b,0x0 -0x88c,0x0 -0x88d,0x0 -0x88e,0x0 -0x88f,0x0 -0x890,0x0 -0x891,0x0 -0x892,0x0 -0x893,0x0 -0x894,0x0 -0x895,0x0 -0x896,0x0 -0x897,0x0 -0x898,0x0 -0x899,0x0 -0x89a,0x0 -0x89b,0x0 -0x89c,0x0 -0x89d,0x0 -0x89e,0x0 -0x89f,0x0 -0x8a0,0x0 -0x8a1,0x0 -0x8a2,0x0 -0x8a3,0x0 -0x8a4,0x0 -0x8a5,0x0 -0x8a6,0x0 -0x8a7,0x0 -0x8a8,0x0 -0x8a9,0x0 -0x8aa,0x0 -0x8ab,0x0 -0x8ac,0x0 -0x8ad,0x0 -0x8ae,0x0 -0x8af,0x0 -0x8b0,0x0 -0x8b1,0x0 -0x8b2,0x0 -0x8b3,0x0 -0x8b4,0x0 -0x8b5,0x0 -0x8b6,0x0 -0x8b7,0x0 -0x8b8,0x0 -0x8b9,0x0 -0x8ba,0x0 -0x8bb,0x0 -0x8bc,0x0 -0x8bd,0x0 -0x8be,0x0 -0x8bf,0x0 -0x8c0,0x0 -0x8c1,0x0 -0x8c2,0x0 -0x8c3,0x0 -0x8c4,0x0 -0x8c5,0x0 -0x8c6,0x0 -0x8c7,0x0 -0x8c8,0x0 -0x8c9,0x0 -0x8ca,0x0 -0x8cb,0x0 -0x8cc,0x0 -0x8cd,0x0 -0x8ce,0x0 -0x8cf,0x0 -0x8d0,0x0 -0x8d1,0x0 -0x8d2,0x0 -0x8d3,0x0 -0x8d4,0x0 -0x8d5,0x0 -0x8d6,0x0 -0x8d7,0x0 -0x8d8,0x0 -0x8d9,0x0 -0x8da,0x0 -0x8db,0x0 -0x8dc,0x0 -0x8dd,0x0 -0x8de,0x0 -0x8df,0x0 -0x8e0,0x0 -0x8e1,0x0 -0x8e2,0x0 -0x8e3,0x0 -0x8e4,0x0 -0x8e5,0x0 -0x8e6,0x0 -0x8e7,0x0 -0x8e8,0x0 -0x8e9,0x0 -0x8ea,0x0 -0x8eb,0x0 -0x8ec,0x0 -0x8ed,0x0 -0x8ee,0x0 -0x8ef,0x0 -0x8f0,0x0 -0x8f1,0x0 -0x8f2,0x0 -0x8f3,0x0 -0x8f4,0x0 -0x8f5,0x0 -0x8f6,0x0 -0x8f7,0x0 -0x8f8,0x0 -0x8f9,0x0 -0x8fa,0x0 -0x8fb,0x0 -0x8fc,0x0 -0x8fd,0x0 -0x8fe,0x0 -0x8ff,0x0 -0xc0000080,0xd01 -0xc0000081,0x23001000000000 -0xc0000082,0xffffffff81800040 -0xc0000083,0xffffffff81801500 -0xc0000084,0x47700 -0xc0000100,0x7ff086f4a740 -0xc0000101,0xffff88803ec00000 -0xc0000102,0x0 -0xc0000103,0x0 -0xc0010000,0x0 -0xc0010001,0x0 -0xc0010002,0x0 -0xc0010003,0x0 -0xc0010004,0x0 -0xc0010005,0x0 -0xc0010006,0x0 -0xc0010007,0x0 -0xc0010010,0x0 -0xc0010015,0x0 -0xc001001b,0x20000000 -0xc001001f,0x0 -0xc0010055,0x0 -0xc0010058,0x0 -0xc0010112,0x0 -0xc0010113,0x0 -0xc0010117,0x0 -0xc0010200,0x0 -0xc0010201,0x0 -0xc0010202,0x0 -0xc0010203,0x0 -0xc0010204,0x0 -0xc0010205,0x0 -0xc0010206,0x0 -0xc0010207,0x0 -0xc0010208,0x0 -0xc0010209,0x0 -0xc001020a,0x0 -0xc001020b,0x0 -0xc0011022,0x0 -0xc0011023,0x0 -0xc001102a,0x0 -0xc001102c,0x0 -0x400000000,0x0 -0x2000000000,0x0 -0x4000000000,0x0 -0x8000000000,0x0 -0x1000000000000,0x0 -0x3c000000000000,0x0 -0x80000000000000,0x0 -0x40000000000000,0x0 diff --git a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_6.1guest.csv b/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_6.1guest.csv deleted file mode 100644 index 8ba340cea6d..00000000000 --- a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_5.10host_6.1guest.csv +++ /dev/null @@ -1,508 +0,0 @@ -MSR_ADDR,VALUE -0x0,0x0 -0x1,0x0 -0x10,0xff34f950 -0x11,0x2748008 -0x12,0x2749001 -0x17,0x0 -0x1b,0xfee00d00 -0x2a,0x0 -0x2c,0x1000000 -0x34,0x0 -0x3a,0x1 -0x3b,0x0 -0x48,0x1 -0x8b,0x100000000 -0xc1,0x0 -0xc2,0x0 -0xcd,0x3 -0xce,0x80000000 -0xfe,0x508 -0x10a,0xc080c4c -0x11e,0xbe702111 -0x140,0x0 -0x174,0x10 -0x175,0xfffffe0000003000 -0x176,0xffffffff81801450 -0x179,0x20 -0x17a,0x0 -0x186,0x0 -0x187,0x0 -0x198,0x400000003e8 -0x199,0x0 -0x1a0,0x1 -0x1d9,0x0 -0x1db,0x0 -0x1dc,0x0 -0x1dd,0x0 -0x1de,0x0 -0x1fc,0x0 -0x200,0x0 -0x201,0x0 -0x202,0x0 -0x203,0x0 -0x204,0x0 -0x205,0x0 -0x206,0x0 -0x207,0x0 -0x208,0x0 -0x209,0x0 -0x20a,0x0 -0x20b,0x0 -0x20c,0x0 -0x20d,0x0 -0x20e,0x0 -0x20f,0x0 -0x250,0x0 -0x258,0x0 -0x259,0x0 -0x268,0x0 -0x269,0x0 -0x26a,0x0 -0x26b,0x0 -0x26c,0x0 -0x26d,0x0 -0x26e,0x0 -0x26f,0x0 -0x277,0x7040600070406 -0x2ff,0x0 -0x400,0x0 -0x401,0x0 -0x402,0x0 -0x403,0x0 -0x404,0x0 -0x405,0x0 -0x406,0x0 -0x407,0x0 -0x408,0x0 -0x409,0x0 -0x40a,0x0 -0x40b,0x0 -0x40c,0x0 -0x40d,0x0 -0x40e,0x0 -0x40f,0x0 -0x410,0x0 -0x411,0x0 -0x412,0x0 -0x413,0x0 -0x414,0x0 -0x415,0x0 -0x416,0x0 -0x417,0x0 -0x418,0x0 -0x419,0x0 -0x41a,0x0 -0x41b,0x0 -0x41c,0x0 -0x41d,0x0 -0x41e,0x0 -0x41f,0x0 -0x420,0x0 -0x421,0x0 -0x422,0x0 -0x423,0x0 -0x424,0x0 -0x425,0x0 -0x426,0x0 -0x427,0x0 -0x428,0x0 -0x429,0x0 -0x42a,0x0 -0x42b,0x0 -0x42c,0x0 -0x42d,0x0 -0x42e,0x0 -0x42f,0x0 -0x430,0x0 -0x431,0x0 -0x432,0x0 -0x433,0x0 -0x434,0x0 -0x435,0x0 -0x436,0x0 -0x437,0x0 -0x438,0x0 -0x439,0x0 -0x43a,0x0 -0x43b,0x0 -0x43c,0x0 -0x43d,0x0 -0x43e,0x0 -0x43f,0x0 -0x440,0x0 -0x441,0x0 -0x442,0x0 -0x443,0x0 -0x444,0x0 -0x445,0x0 -0x446,0x0 -0x447,0x0 -0x448,0x0 -0x449,0x0 -0x44a,0x0 -0x44b,0x0 -0x44c,0x0 -0x44d,0x0 -0x44e,0x0 -0x44f,0x0 -0x450,0x0 -0x451,0x0 -0x452,0x0 -0x453,0x0 -0x454,0x0 -0x455,0x0 -0x456,0x0 -0x457,0x0 -0x458,0x0 -0x459,0x0 -0x45a,0x0 -0x45b,0x0 -0x45c,0x0 -0x45d,0x0 -0x45e,0x0 -0x45f,0x0 -0x460,0x0 -0x461,0x0 -0x462,0x0 -0x463,0x0 -0x464,0x0 -0x465,0x0 -0x466,0x0 -0x467,0x0 -0x468,0x0 -0x469,0x0 -0x46a,0x0 -0x46b,0x0 -0x46c,0x0 -0x46d,0x0 -0x46e,0x0 -0x46f,0x0 -0x470,0x0 -0x471,0x0 -0x472,0x0 -0x473,0x0 -0x474,0x0 -0x475,0x0 -0x476,0x0 -0x477,0x0 -0x478,0x0 -0x479,0x0 -0x47a,0x0 -0x47b,0x0 -0x47c,0x0 -0x47d,0x0 -0x47e,0x0 -0x47f,0x0 -0x606,0x0 -0x611,0x0 -0x619,0x0 -0x639,0x0 -0x641,0x0 -0x6e0,0x2d1e43b52 -0x800,0x0 -0x801,0x0 -0x802,0x0 -0x803,0x50014 -0x804,0x0 -0x805,0x0 -0x806,0x0 -0x807,0x0 -0x808,0x10 -0x809,0x0 -0x80a,0x10 -0x80b,0x0 -0x80c,0x0 -0x80d,0x1 -0x80e,0xffffffff -0x80f,0x1ff -0x810,0x0 -0x811,0x0 -0x812,0x0 -0x813,0x0 -0x814,0x0 -0x815,0x0 -0x816,0x0 -0x817,0x0 -0x818,0x0 -0x819,0x0 -0x81a,0x0 -0x81b,0x0 -0x81c,0x0 -0x81d,0x0 -0x81e,0x0 -0x81f,0x0 -0x820,0x0 -0x821,0x0 -0x822,0x0 -0x823,0x0 -0x824,0x0 -0x825,0x0 -0x826,0x0 -0x827,0x0 -0x828,0x0 -0x829,0x0 -0x82a,0x0 -0x82b,0x0 -0x82c,0x0 -0x82d,0x0 -0x82e,0x0 -0x82f,0x0 -0x830,0x0 -0x831,0x0 -0x832,0x400ec -0x833,0x10000 -0x834,0x10000 -0x835,0x10700 -0x836,0x400 -0x837,0xfe -0x838,0x0 -0x839,0x0 -0x83a,0x0 -0x83b,0x0 -0x83c,0x0 -0x83d,0x0 -0x83e,0x0 -0x83f,0x0 -0x840,0x0 -0x841,0x0 -0x842,0x0 -0x843,0x0 -0x844,0x0 -0x845,0x0 -0x846,0x0 -0x847,0x0 -0x848,0x0 -0x849,0x0 -0x84a,0x0 -0x84b,0x0 -0x84c,0x0 -0x84d,0x0 -0x84e,0x0 -0x84f,0x0 -0x850,0x0 -0x851,0x0 -0x852,0x0 -0x853,0x0 -0x854,0x0 -0x855,0x0 -0x856,0x0 -0x857,0x0 -0x858,0x0 -0x859,0x0 -0x85a,0x0 -0x85b,0x0 -0x85c,0x0 -0x85d,0x0 -0x85e,0x0 -0x85f,0x0 -0x860,0x0 -0x861,0x0 -0x862,0x0 -0x863,0x0 -0x864,0x0 -0x865,0x0 -0x866,0x0 -0x867,0x0 -0x868,0x0 -0x869,0x0 -0x86a,0x0 -0x86b,0x0 -0x86c,0x0 -0x86d,0x0 -0x86e,0x0 -0x86f,0x0 -0x870,0x0 -0x871,0x0 -0x872,0x0 -0x873,0x0 -0x874,0x0 -0x875,0x0 -0x876,0x0 -0x877,0x0 -0x878,0x0 -0x879,0x0 -0x87a,0x0 -0x87b,0x0 -0x87c,0x0 -0x87d,0x0 -0x87e,0x0 -0x87f,0x0 -0x880,0x0 -0x881,0x0 -0x882,0x0 -0x883,0x0 -0x884,0x0 -0x885,0x0 -0x886,0x0 -0x887,0x0 -0x888,0x0 -0x889,0x0 -0x88a,0x0 -0x88b,0x0 -0x88c,0x0 -0x88d,0x0 -0x88e,0x0 -0x88f,0x0 -0x890,0x0 -0x891,0x0 -0x892,0x0 -0x893,0x0 -0x894,0x0 -0x895,0x0 -0x896,0x0 -0x897,0x0 -0x898,0x0 -0x899,0x0 -0x89a,0x0 -0x89b,0x0 -0x89c,0x0 -0x89d,0x0 -0x89e,0x0 -0x89f,0x0 -0x8a0,0x0 -0x8a1,0x0 -0x8a2,0x0 -0x8a3,0x0 -0x8a4,0x0 -0x8a5,0x0 -0x8a6,0x0 -0x8a7,0x0 -0x8a8,0x0 -0x8a9,0x0 -0x8aa,0x0 -0x8ab,0x0 -0x8ac,0x0 -0x8ad,0x0 -0x8ae,0x0 -0x8af,0x0 -0x8b0,0x0 -0x8b1,0x0 -0x8b2,0x0 -0x8b3,0x0 -0x8b4,0x0 -0x8b5,0x0 -0x8b6,0x0 -0x8b7,0x0 -0x8b8,0x0 -0x8b9,0x0 -0x8ba,0x0 -0x8bb,0x0 -0x8bc,0x0 -0x8bd,0x0 -0x8be,0x0 -0x8bf,0x0 -0x8c0,0x0 -0x8c1,0x0 -0x8c2,0x0 -0x8c3,0x0 -0x8c4,0x0 -0x8c5,0x0 -0x8c6,0x0 -0x8c7,0x0 -0x8c8,0x0 -0x8c9,0x0 -0x8ca,0x0 -0x8cb,0x0 -0x8cc,0x0 -0x8cd,0x0 -0x8ce,0x0 -0x8cf,0x0 -0x8d0,0x0 -0x8d1,0x0 -0x8d2,0x0 -0x8d3,0x0 -0x8d4,0x0 -0x8d5,0x0 -0x8d6,0x0 -0x8d7,0x0 -0x8d8,0x0 -0x8d9,0x0 -0x8da,0x0 -0x8db,0x0 -0x8dc,0x0 -0x8dd,0x0 -0x8de,0x0 -0x8df,0x0 -0x8e0,0x0 -0x8e1,0x0 -0x8e2,0x0 -0x8e3,0x0 -0x8e4,0x0 -0x8e5,0x0 -0x8e6,0x0 -0x8e7,0x0 -0x8e8,0x0 -0x8e9,0x0 -0x8ea,0x0 -0x8eb,0x0 -0x8ec,0x0 -0x8ed,0x0 -0x8ee,0x0 -0x8ef,0x0 -0x8f0,0x0 -0x8f1,0x0 -0x8f2,0x0 -0x8f3,0x0 -0x8f4,0x0 -0x8f5,0x0 -0x8f6,0x0 -0x8f7,0x0 -0x8f8,0x0 -0x8f9,0x0 -0x8fa,0x0 -0x8fb,0x0 -0x8fc,0x0 -0x8fd,0x0 -0x8fe,0x0 -0x8ff,0x0 -0xc0000080,0xd01 -0xc0000081,0x23001000000000 -0xc0000082,0xffffffff81800040 -0xc0000083,0xffffffff81801500 -0xc0000084,0x257fd5 -0xc0000100,0x7ff086f4a740 -0xc0000101,0xffff88803ec00000 -0xc0000102,0x0 -0xc0000103,0x0 -0xc0010000,0x0 -0xc0010001,0x0 -0xc0010002,0x0 -0xc0010003,0x0 -0xc0010004,0x0 -0xc0010005,0x0 -0xc0010006,0x0 -0xc0010007,0x0 -0xc0010010,0x0 -0xc0010015,0x0 -0xc001001b,0x20000000 -0xc001001f,0x0 -0xc0010055,0x0 -0xc0010058,0x0 -0xc0010112,0x0 -0xc0010113,0x0 -0xc0010117,0x0 -0xc0010200,0x0 -0xc0010201,0x0 -0xc0010202,0x0 -0xc0010203,0x0 -0xc0010204,0x0 -0xc0010205,0x0 -0xc0010206,0x0 -0xc0010207,0x0 -0xc0010208,0x0 -0xc0010209,0x0 -0xc001020a,0x0 -0xc001020b,0x0 -0xc0011022,0x0 -0xc0011023,0x0 -0xc001102a,0x0 -0xc001102c,0x0 -0x400000000,0x0 -0x2000000000,0x0 -0x4000000000,0x0 -0x8000000000,0x0 -0x1000000000000,0x0 -0x3c000000000000,0x0 -0x80000000000000,0x0 -0x40000000000000,0x0 diff --git a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_5.10guest.csv b/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_5.10guest.csv deleted file mode 100644 index 8cb7d9379a8..00000000000 --- a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_5.10guest.csv +++ /dev/null @@ -1,496 +0,0 @@ -MSR_ADDR,VALUE -0x0,0x0 -0x1,0x0 -0x10,0x1000556b4 -0x11,0x2748008 -0x12,0x2749001 -0x17,0x0 -0x1b,0xfee00d00 -0x2a,0x0 -0x2c,0x1000000 -0x34,0x0 -0x3a,0x1 -0x3b,0x0 -0x48,0x1 -0x8b,0x100000000 -0xc1,0x0 -0xc2,0x0 -0xcd,0x3 -0xce,0x80000000 -0xfe,0x508 -0x10a,0xc080c4c -0x11e,0xbe702111 -0x140,0x0 -0x174,0x10 -0x175,0xfffffe0000003000 -0x176,0xffffffff81801450 -0x179,0x20 -0x17a,0x0 -0x186,0x0 -0x187,0x0 -0x198,0x400000003e8 -0x199,0x0 -0x1a0,0x1 -0x1d9,0x0 -0x1db,0x0 -0x1dc,0x0 -0x1dd,0x0 -0x1de,0x0 -0x1fc,0x0 -0x200,0x0 -0x201,0x0 -0x202,0x0 -0x203,0x0 -0x204,0x0 -0x205,0x0 -0x206,0x0 -0x207,0x0 -0x208,0x0 -0x209,0x0 -0x20a,0x0 -0x20b,0x0 -0x20c,0x0 -0x20d,0x0 -0x20e,0x0 -0x20f,0x0 -0x250,0x0 -0x258,0x0 -0x259,0x0 -0x268,0x0 -0x269,0x0 -0x26a,0x0 -0x26b,0x0 -0x26c,0x0 -0x26d,0x0 -0x26e,0x0 -0x26f,0x0 -0x277,0x7040600070406 -0x2ff,0x0 -0x400,0x0 -0x401,0x0 -0x402,0x0 -0x403,0x0 -0x404,0x0 -0x405,0x0 -0x406,0x0 -0x407,0x0 -0x408,0x0 -0x409,0x0 -0x40a,0x0 -0x40b,0x0 -0x40c,0x0 -0x40d,0x0 -0x40e,0x0 -0x40f,0x0 -0x410,0x0 -0x411,0x0 -0x412,0x0 -0x413,0x0 -0x414,0x0 -0x415,0x0 -0x416,0x0 -0x417,0x0 -0x418,0x0 -0x419,0x0 -0x41a,0x0 -0x41b,0x0 -0x41c,0x0 -0x41d,0x0 -0x41e,0x0 -0x41f,0x0 -0x420,0x0 -0x421,0x0 -0x422,0x0 -0x423,0x0 -0x424,0x0 -0x425,0x0 -0x426,0x0 -0x427,0x0 -0x428,0x0 -0x429,0x0 -0x42a,0x0 -0x42b,0x0 -0x42c,0x0 -0x42d,0x0 -0x42e,0x0 -0x42f,0x0 -0x430,0x0 -0x431,0x0 -0x432,0x0 -0x433,0x0 -0x434,0x0 -0x435,0x0 -0x436,0x0 -0x437,0x0 -0x438,0x0 -0x439,0x0 -0x43a,0x0 -0x43b,0x0 -0x43c,0x0 -0x43d,0x0 -0x43e,0x0 -0x43f,0x0 -0x440,0x0 -0x441,0x0 -0x442,0x0 -0x443,0x0 -0x444,0x0 -0x445,0x0 -0x446,0x0 -0x447,0x0 -0x448,0x0 -0x449,0x0 -0x44a,0x0 -0x44b,0x0 -0x44c,0x0 -0x44d,0x0 -0x44e,0x0 -0x44f,0x0 -0x450,0x0 -0x451,0x0 -0x452,0x0 -0x453,0x0 -0x454,0x0 -0x455,0x0 -0x456,0x0 -0x457,0x0 -0x458,0x0 -0x459,0x0 -0x45a,0x0 -0x45b,0x0 -0x45c,0x0 -0x45d,0x0 -0x45e,0x0 -0x45f,0x0 -0x460,0x0 -0x461,0x0 -0x462,0x0 -0x463,0x0 -0x464,0x0 -0x465,0x0 -0x466,0x0 -0x467,0x0 -0x468,0x0 -0x469,0x0 -0x46a,0x0 -0x46b,0x0 -0x46c,0x0 -0x46d,0x0 -0x46e,0x0 -0x46f,0x0 -0x470,0x0 -0x471,0x0 -0x472,0x0 -0x473,0x0 -0x474,0x0 -0x475,0x0 -0x476,0x0 -0x477,0x0 -0x478,0x0 -0x479,0x0 -0x47a,0x0 -0x47b,0x0 -0x47c,0x0 -0x47d,0x0 -0x47e,0x0 -0x47f,0x0 -0x606,0x0 -0x611,0x0 -0x619,0x0 -0x639,0x0 -0x641,0x0 -0x6e0,0x2d4880d12 -0x800,0x0 -0x801,0x0 -0x802,0x0 -0x803,0x50014 -0x804,0x0 -0x805,0x0 -0x806,0x0 -0x807,0x0 -0x808,0x10 -0x809,0x0 -0x80a,0x10 -0x80b,0x0 -0x80c,0x0 -0x80d,0x1 -0x80e,0xffffffff -0x80f,0x1ff -0x810,0x0 -0x811,0x0 -0x812,0x0 -0x813,0x0 -0x814,0x0 -0x815,0x0 -0x816,0x0 -0x817,0x0 -0x818,0x0 -0x819,0x0 -0x81a,0x0 -0x81b,0x0 -0x81c,0x0 -0x81d,0x0 -0x81e,0x0 -0x81f,0x0 -0x820,0x0 -0x821,0x0 -0x822,0x0 -0x823,0x0 -0x824,0x0 -0x825,0x0 -0x826,0x0 -0x827,0x0 -0x828,0x0 -0x829,0x0 -0x82a,0x0 -0x82b,0x0 -0x82c,0x0 -0x82d,0x0 -0x82e,0x0 -0x82f,0x0 -0x830,0x0 -0x831,0x0 -0x832,0x400ec -0x833,0x10000 -0x834,0x10000 -0x835,0x10700 -0x836,0x400 -0x837,0xfe -0x838,0x0 -0x839,0x0 -0x83a,0x0 -0x83b,0x0 -0x83c,0x0 -0x83d,0x0 -0x83e,0x0 -0x83f,0x0 -0x840,0x0 -0x841,0x0 -0x842,0x0 -0x843,0x0 -0x844,0x0 -0x845,0x0 -0x846,0x0 -0x847,0x0 -0x848,0x0 -0x849,0x0 -0x84a,0x0 -0x84b,0x0 -0x84c,0x0 -0x84d,0x0 -0x84e,0x0 -0x84f,0x0 -0x850,0x0 -0x851,0x0 -0x852,0x0 -0x853,0x0 -0x854,0x0 -0x855,0x0 -0x856,0x0 -0x857,0x0 -0x858,0x0 -0x859,0x0 -0x85a,0x0 -0x85b,0x0 -0x85c,0x0 -0x85d,0x0 -0x85e,0x0 -0x85f,0x0 -0x860,0x0 -0x861,0x0 -0x862,0x0 -0x863,0x0 -0x864,0x0 -0x865,0x0 -0x866,0x0 -0x867,0x0 -0x868,0x0 -0x869,0x0 -0x86a,0x0 -0x86b,0x0 -0x86c,0x0 -0x86d,0x0 -0x86e,0x0 -0x86f,0x0 -0x870,0x0 -0x871,0x0 -0x872,0x0 -0x873,0x0 -0x874,0x0 -0x875,0x0 -0x876,0x0 -0x877,0x0 -0x878,0x0 -0x879,0x0 -0x87a,0x0 -0x87b,0x0 -0x87c,0x0 -0x87d,0x0 -0x87e,0x0 -0x87f,0x0 -0x880,0x0 -0x881,0x0 -0x882,0x0 -0x883,0x0 -0x884,0x0 -0x885,0x0 -0x886,0x0 -0x887,0x0 -0x888,0x0 -0x889,0x0 -0x88a,0x0 -0x88b,0x0 -0x88c,0x0 -0x88d,0x0 -0x88e,0x0 -0x88f,0x0 -0x890,0x0 -0x891,0x0 -0x892,0x0 -0x893,0x0 -0x894,0x0 -0x895,0x0 -0x896,0x0 -0x897,0x0 -0x898,0x0 -0x899,0x0 -0x89a,0x0 -0x89b,0x0 -0x89c,0x0 -0x89d,0x0 -0x89e,0x0 -0x89f,0x0 -0x8a0,0x0 -0x8a1,0x0 -0x8a2,0x0 -0x8a3,0x0 -0x8a4,0x0 -0x8a5,0x0 -0x8a6,0x0 -0x8a7,0x0 -0x8a8,0x0 -0x8a9,0x0 -0x8aa,0x0 -0x8ab,0x0 -0x8ac,0x0 -0x8ad,0x0 -0x8ae,0x0 -0x8af,0x0 -0x8b0,0x0 -0x8b1,0x0 -0x8b2,0x0 -0x8b3,0x0 -0x8b4,0x0 -0x8b5,0x0 -0x8b6,0x0 -0x8b7,0x0 -0x8b8,0x0 -0x8b9,0x0 -0x8ba,0x0 -0x8bb,0x0 -0x8bc,0x0 -0x8bd,0x0 -0x8be,0x0 -0x8bf,0x0 -0x8c0,0x0 -0x8c1,0x0 -0x8c2,0x0 -0x8c3,0x0 -0x8c4,0x0 -0x8c5,0x0 -0x8c6,0x0 -0x8c7,0x0 -0x8c8,0x0 -0x8c9,0x0 -0x8ca,0x0 -0x8cb,0x0 -0x8cc,0x0 -0x8cd,0x0 -0x8ce,0x0 -0x8cf,0x0 -0x8d0,0x0 -0x8d1,0x0 -0x8d2,0x0 -0x8d3,0x0 -0x8d4,0x0 -0x8d5,0x0 -0x8d6,0x0 -0x8d7,0x0 -0x8d8,0x0 -0x8d9,0x0 -0x8da,0x0 -0x8db,0x0 -0x8dc,0x0 -0x8dd,0x0 -0x8de,0x0 -0x8df,0x0 -0x8e0,0x0 -0x8e1,0x0 -0x8e2,0x0 -0x8e3,0x0 -0x8e4,0x0 -0x8e5,0x0 -0x8e6,0x0 -0x8e7,0x0 -0x8e8,0x0 -0x8e9,0x0 -0x8ea,0x0 -0x8eb,0x0 -0x8ec,0x0 -0x8ed,0x0 -0x8ee,0x0 -0x8ef,0x0 -0x8f0,0x0 -0x8f1,0x0 -0x8f2,0x0 -0x8f3,0x0 -0x8f4,0x0 -0x8f5,0x0 -0x8f6,0x0 -0x8f7,0x0 -0x8f8,0x0 -0x8f9,0x0 -0x8fa,0x0 -0x8fb,0x0 -0x8fc,0x0 -0x8fd,0x0 -0x8fe,0x0 -0x8ff,0x0 -0xc0000080,0xd01 -0xc0000081,0x23001000000000 -0xc0000082,0xffffffff81800040 -0xc0000083,0xffffffff81801500 -0xc0000084,0x47700 -0xc0000100,0x7f4e02611740 -0xc0000101,0xffff88803ec00000 -0xc0000102,0x0 -0xc0000103,0x0 -0xc0010000,0x0 -0xc0010001,0x0 -0xc0010002,0x0 -0xc0010003,0x0 -0xc0010004,0x0 -0xc0010005,0x0 -0xc0010006,0x0 -0xc0010007,0x0 -0xc0010010,0x0 -0xc0010015,0x0 -0xc001001b,0x20000000 -0xc001001f,0x0 -0xc0010055,0x0 -0xc0010058,0x0 -0xc0010112,0x0 -0xc0010113,0x0 -0xc0010117,0x0 -0xc0011022,0x0 -0xc0011023,0x0 -0xc001102a,0x0 -0xc001102c,0x0 -0x400000000,0x0 -0x2000000000,0x0 -0x4000000000,0x0 -0x8000000000,0x0 -0x1000000000000,0x0 -0x3c000000000000,0x0 -0x80000000000000,0x0 -0x40000000000000,0x0 diff --git a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_6.1guest.csv b/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_6.1guest.csv deleted file mode 100644 index 2952a73b658..00000000000 --- a/tests/data/msr/msr_list_T2S_INTEL_SKYLAKE_6.1host_6.1guest.csv +++ /dev/null @@ -1,496 +0,0 @@ -MSR_ADDR,VALUE -0x0,0x0 -0x1,0x0 -0x10,0x1000556b4 -0x11,0x2748008 -0x12,0x2749001 -0x17,0x0 -0x1b,0xfee00d00 -0x2a,0x0 -0x2c,0x1000000 -0x34,0x0 -0x3a,0x1 -0x3b,0x0 -0x48,0x1 -0x8b,0x100000000 -0xc1,0x0 -0xc2,0x0 -0xcd,0x3 -0xce,0x80000000 -0xfe,0x508 -0x10a,0xc080c4c -0x11e,0xbe702111 -0x140,0x0 -0x174,0x10 -0x175,0xfffffe0000003000 -0x176,0xffffffff81801450 -0x179,0x20 -0x17a,0x0 -0x186,0x0 -0x187,0x0 -0x198,0x400000003e8 -0x199,0x0 -0x1a0,0x1 -0x1d9,0x0 -0x1db,0x0 -0x1dc,0x0 -0x1dd,0x0 -0x1de,0x0 -0x1fc,0x0 -0x200,0x0 -0x201,0x0 -0x202,0x0 -0x203,0x0 -0x204,0x0 -0x205,0x0 -0x206,0x0 -0x207,0x0 -0x208,0x0 -0x209,0x0 -0x20a,0x0 -0x20b,0x0 -0x20c,0x0 -0x20d,0x0 -0x20e,0x0 -0x20f,0x0 -0x250,0x0 -0x258,0x0 -0x259,0x0 -0x268,0x0 -0x269,0x0 -0x26a,0x0 -0x26b,0x0 -0x26c,0x0 -0x26d,0x0 -0x26e,0x0 -0x26f,0x0 -0x277,0x7040600070406 -0x2ff,0x0 -0x400,0x0 -0x401,0x0 -0x402,0x0 -0x403,0x0 -0x404,0x0 -0x405,0x0 -0x406,0x0 -0x407,0x0 -0x408,0x0 -0x409,0x0 -0x40a,0x0 -0x40b,0x0 -0x40c,0x0 -0x40d,0x0 -0x40e,0x0 -0x40f,0x0 -0x410,0x0 -0x411,0x0 -0x412,0x0 -0x413,0x0 -0x414,0x0 -0x415,0x0 -0x416,0x0 -0x417,0x0 -0x418,0x0 -0x419,0x0 -0x41a,0x0 -0x41b,0x0 -0x41c,0x0 -0x41d,0x0 -0x41e,0x0 -0x41f,0x0 -0x420,0x0 -0x421,0x0 -0x422,0x0 -0x423,0x0 -0x424,0x0 -0x425,0x0 -0x426,0x0 -0x427,0x0 -0x428,0x0 -0x429,0x0 -0x42a,0x0 -0x42b,0x0 -0x42c,0x0 -0x42d,0x0 -0x42e,0x0 -0x42f,0x0 -0x430,0x0 -0x431,0x0 -0x432,0x0 -0x433,0x0 -0x434,0x0 -0x435,0x0 -0x436,0x0 -0x437,0x0 -0x438,0x0 -0x439,0x0 -0x43a,0x0 -0x43b,0x0 -0x43c,0x0 -0x43d,0x0 -0x43e,0x0 -0x43f,0x0 -0x440,0x0 -0x441,0x0 -0x442,0x0 -0x443,0x0 -0x444,0x0 -0x445,0x0 -0x446,0x0 -0x447,0x0 -0x448,0x0 -0x449,0x0 -0x44a,0x0 -0x44b,0x0 -0x44c,0x0 -0x44d,0x0 -0x44e,0x0 -0x44f,0x0 -0x450,0x0 -0x451,0x0 -0x452,0x0 -0x453,0x0 -0x454,0x0 -0x455,0x0 -0x456,0x0 -0x457,0x0 -0x458,0x0 -0x459,0x0 -0x45a,0x0 -0x45b,0x0 -0x45c,0x0 -0x45d,0x0 -0x45e,0x0 -0x45f,0x0 -0x460,0x0 -0x461,0x0 -0x462,0x0 -0x463,0x0 -0x464,0x0 -0x465,0x0 -0x466,0x0 -0x467,0x0 -0x468,0x0 -0x469,0x0 -0x46a,0x0 -0x46b,0x0 -0x46c,0x0 -0x46d,0x0 -0x46e,0x0 -0x46f,0x0 -0x470,0x0 -0x471,0x0 -0x472,0x0 -0x473,0x0 -0x474,0x0 -0x475,0x0 -0x476,0x0 -0x477,0x0 -0x478,0x0 -0x479,0x0 -0x47a,0x0 -0x47b,0x0 -0x47c,0x0 -0x47d,0x0 -0x47e,0x0 -0x47f,0x0 -0x606,0x0 -0x611,0x0 -0x619,0x0 -0x639,0x0 -0x641,0x0 -0x6e0,0x2d4880d12 -0x800,0x0 -0x801,0x0 -0x802,0x0 -0x803,0x50014 -0x804,0x0 -0x805,0x0 -0x806,0x0 -0x807,0x0 -0x808,0x10 -0x809,0x0 -0x80a,0x10 -0x80b,0x0 -0x80c,0x0 -0x80d,0x1 -0x80e,0xffffffff -0x80f,0x1ff -0x810,0x0 -0x811,0x0 -0x812,0x0 -0x813,0x0 -0x814,0x0 -0x815,0x0 -0x816,0x0 -0x817,0x0 -0x818,0x0 -0x819,0x0 -0x81a,0x0 -0x81b,0x0 -0x81c,0x0 -0x81d,0x0 -0x81e,0x0 -0x81f,0x0 -0x820,0x0 -0x821,0x0 -0x822,0x0 -0x823,0x0 -0x824,0x0 -0x825,0x0 -0x826,0x0 -0x827,0x0 -0x828,0x0 -0x829,0x0 -0x82a,0x0 -0x82b,0x0 -0x82c,0x0 -0x82d,0x0 -0x82e,0x0 -0x82f,0x0 -0x830,0x0 -0x831,0x0 -0x832,0x400ec -0x833,0x10000 -0x834,0x10000 -0x835,0x10700 -0x836,0x400 -0x837,0xfe -0x838,0x0 -0x839,0x0 -0x83a,0x0 -0x83b,0x0 -0x83c,0x0 -0x83d,0x0 -0x83e,0x0 -0x83f,0x0 -0x840,0x0 -0x841,0x0 -0x842,0x0 -0x843,0x0 -0x844,0x0 -0x845,0x0 -0x846,0x0 -0x847,0x0 -0x848,0x0 -0x849,0x0 -0x84a,0x0 -0x84b,0x0 -0x84c,0x0 -0x84d,0x0 -0x84e,0x0 -0x84f,0x0 -0x850,0x0 -0x851,0x0 -0x852,0x0 -0x853,0x0 -0x854,0x0 -0x855,0x0 -0x856,0x0 -0x857,0x0 -0x858,0x0 -0x859,0x0 -0x85a,0x0 -0x85b,0x0 -0x85c,0x0 -0x85d,0x0 -0x85e,0x0 -0x85f,0x0 -0x860,0x0 -0x861,0x0 -0x862,0x0 -0x863,0x0 -0x864,0x0 -0x865,0x0 -0x866,0x0 -0x867,0x0 -0x868,0x0 -0x869,0x0 -0x86a,0x0 -0x86b,0x0 -0x86c,0x0 -0x86d,0x0 -0x86e,0x0 -0x86f,0x0 -0x870,0x0 -0x871,0x0 -0x872,0x0 -0x873,0x0 -0x874,0x0 -0x875,0x0 -0x876,0x0 -0x877,0x0 -0x878,0x0 -0x879,0x0 -0x87a,0x0 -0x87b,0x0 -0x87c,0x0 -0x87d,0x0 -0x87e,0x0 -0x87f,0x0 -0x880,0x0 -0x881,0x0 -0x882,0x0 -0x883,0x0 -0x884,0x0 -0x885,0x0 -0x886,0x0 -0x887,0x0 -0x888,0x0 -0x889,0x0 -0x88a,0x0 -0x88b,0x0 -0x88c,0x0 -0x88d,0x0 -0x88e,0x0 -0x88f,0x0 -0x890,0x0 -0x891,0x0 -0x892,0x0 -0x893,0x0 -0x894,0x0 -0x895,0x0 -0x896,0x0 -0x897,0x0 -0x898,0x0 -0x899,0x0 -0x89a,0x0 -0x89b,0x0 -0x89c,0x0 -0x89d,0x0 -0x89e,0x0 -0x89f,0x0 -0x8a0,0x0 -0x8a1,0x0 -0x8a2,0x0 -0x8a3,0x0 -0x8a4,0x0 -0x8a5,0x0 -0x8a6,0x0 -0x8a7,0x0 -0x8a8,0x0 -0x8a9,0x0 -0x8aa,0x0 -0x8ab,0x0 -0x8ac,0x0 -0x8ad,0x0 -0x8ae,0x0 -0x8af,0x0 -0x8b0,0x0 -0x8b1,0x0 -0x8b2,0x0 -0x8b3,0x0 -0x8b4,0x0 -0x8b5,0x0 -0x8b6,0x0 -0x8b7,0x0 -0x8b8,0x0 -0x8b9,0x0 -0x8ba,0x0 -0x8bb,0x0 -0x8bc,0x0 -0x8bd,0x0 -0x8be,0x0 -0x8bf,0x0 -0x8c0,0x0 -0x8c1,0x0 -0x8c2,0x0 -0x8c3,0x0 -0x8c4,0x0 -0x8c5,0x0 -0x8c6,0x0 -0x8c7,0x0 -0x8c8,0x0 -0x8c9,0x0 -0x8ca,0x0 -0x8cb,0x0 -0x8cc,0x0 -0x8cd,0x0 -0x8ce,0x0 -0x8cf,0x0 -0x8d0,0x0 -0x8d1,0x0 -0x8d2,0x0 -0x8d3,0x0 -0x8d4,0x0 -0x8d5,0x0 -0x8d6,0x0 -0x8d7,0x0 -0x8d8,0x0 -0x8d9,0x0 -0x8da,0x0 -0x8db,0x0 -0x8dc,0x0 -0x8dd,0x0 -0x8de,0x0 -0x8df,0x0 -0x8e0,0x0 -0x8e1,0x0 -0x8e2,0x0 -0x8e3,0x0 -0x8e4,0x0 -0x8e5,0x0 -0x8e6,0x0 -0x8e7,0x0 -0x8e8,0x0 -0x8e9,0x0 -0x8ea,0x0 -0x8eb,0x0 -0x8ec,0x0 -0x8ed,0x0 -0x8ee,0x0 -0x8ef,0x0 -0x8f0,0x0 -0x8f1,0x0 -0x8f2,0x0 -0x8f3,0x0 -0x8f4,0x0 -0x8f5,0x0 -0x8f6,0x0 -0x8f7,0x0 -0x8f8,0x0 -0x8f9,0x0 -0x8fa,0x0 -0x8fb,0x0 -0x8fc,0x0 -0x8fd,0x0 -0x8fe,0x0 -0x8ff,0x0 -0xc0000080,0xd01 -0xc0000081,0x23001000000000 -0xc0000082,0xffffffff81800040 -0xc0000083,0xffffffff81801500 -0xc0000084,0x257fd5 -0xc0000100,0x7f4e02611740 -0xc0000101,0xffff88803ec00000 -0xc0000102,0x0 -0xc0000103,0x0 -0xc0010000,0x0 -0xc0010001,0x0 -0xc0010002,0x0 -0xc0010003,0x0 -0xc0010004,0x0 -0xc0010005,0x0 -0xc0010006,0x0 -0xc0010007,0x0 -0xc0010010,0x0 -0xc0010015,0x0 -0xc001001b,0x20000000 -0xc001001f,0x0 -0xc0010055,0x0 -0xc0010058,0x0 -0xc0010112,0x0 -0xc0010113,0x0 -0xc0010117,0x0 -0xc0011022,0x0 -0xc0011023,0x0 -0xc001102a,0x0 -0xc001102c,0x0 -0x400000000,0x0 -0x2000000000,0x0 -0x4000000000,0x0 -0x8000000000,0x0 -0x1000000000000,0x0 -0x3c000000000000,0x0 -0x80000000000000,0x0 -0x40000000000000,0x0 diff --git a/tests/framework/http_api.py b/tests/framework/http_api.py index 16990a2a927..6977580e07b 100644 --- a/tests/framework/http_api.py +++ b/tests/framework/http_api.py @@ -133,3 +133,4 @@ def __init__(self, api_usocket_full_name, *, on_error=None): self.cpu_config = Resource(self, "/cpu-config") self.entropy = Resource(self, "/entropy") self.serial = Resource(self, "/serial") + self.memory_hotplug = Resource(self, "/hotplug/memory") diff --git a/tests/framework/properties.py b/tests/framework/properties.py index 29041ab6e64..0c430cfd41d 100644 --- a/tests/framework/properties.py +++ b/tests/framework/properties.py @@ -26,7 +26,7 @@ def get_os_version(): """Get the OS version >>> get_os_version() - 'Ubuntu 24.04.2 LTS' + 'Ubuntu 24.04.3 LTS' """ os_release = Path("/etc/os-release").read_text(encoding="ascii") diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py index 372d9a11bad..dcfc98b6d3d 100644 --- a/tests/framework/utils_cpu_templates.py +++ b/tests/framework/utils_cpu_templates.py @@ -25,8 +25,6 @@ def get_supported_cpu_templates(): """Return the list of static CPU templates supported by the platform.""" host_linux = global_props.host_linux_version_tpl match get_cpu_vendor(), global_props.cpu_codename: - case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: - return sorted(set(INTEL_TEMPLATES) - {"T2CL"}) case CpuVendor.INTEL, CpuModel.INTEL_CASCADELAKE: return INTEL_TEMPLATES case CpuVendor.INTEL, CpuModel.INTEL_ICELAKE: @@ -46,8 +44,6 @@ def get_supported_custom_cpu_templates(): """Return the list of custom CPU templates supported by the platform.""" host_linux = global_props.host_linux_version_tpl match get_cpu_vendor(), global_props.cpu_codename: - case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE: - return set(INTEL_TEMPLATES) - {"T2CL"} case CpuVendor.INTEL, CpuModel.INTEL_CASCADELAKE: return INTEL_TEMPLATES case CpuVendor.INTEL, CpuModel.INTEL_ICELAKE: diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py index 8e93f60a9a8..73a0e6b5373 100644 --- a/tests/framework/utils_cpuid.py +++ b/tests/framework/utils_cpuid.py @@ -29,7 +29,6 @@ class CpuModel(str, Enum): ARM_NEOVERSE_N1 = "ARM_NEOVERSE_N1" ARM_NEOVERSE_V1 = "ARM_NEOVERSE_V1" ARM_NEOVERSE_V2 = "ARM_NEOVERSE_V2" - INTEL_SKYLAKE = "INTEL_SKYLAKE" INTEL_CASCADELAKE = "INTEL_CASCADELAKE" INTEL_ICELAKE = "INTEL_ICELAKE" INTEL_SAPPHIRE_RAPIDS = "INTEL_SAPPHIRE_RAPIDS" @@ -37,8 +36,6 @@ class CpuModel(str, Enum): CPU_DICT = { CpuVendor.INTEL: { - "Intel(R) Xeon(R) Platinum 8175M CPU": "INTEL_SKYLAKE", - "Intel(R) Xeon(R) Platinum 8124M CPU": "INTEL_SKYLAKE", "Intel(R) Xeon(R) Platinum 8259CL CPU": "INTEL_CASCADELAKE", "Intel(R) Xeon(R) Platinum 8375C CPU": "INTEL_ICELAKE", "Intel(R) Xeon(R) Platinum 8488C": "INTEL_SAPPHIRE_RAPIDS", diff --git a/tests/framework/vm_config.json b/tests/framework/vm_config.json index 6948002e245..1d7ca27f5e4 100644 --- a/tests/framework/vm_config.json +++ b/tests/framework/vm_config.json @@ -31,5 +31,6 @@ "logger": null, "metrics": null, "mmds-config": null, - "entropy": null + "entropy": null, + "memory-hotplug": null } diff --git a/tests/host_tools/fcmetrics.py b/tests/host_tools/fcmetrics.py index e2a1862c21f..00da02423ec 100644 --- a/tests/host_tools/fcmetrics.py +++ b/tests/host_tools/fcmetrics.py @@ -153,6 +153,7 @@ def validate_fc_metrics(metrics): "machine_cfg_count", "mmds_count", "vmm_version_count", + "hotplug_memory_count", ], "i8042": [ "error_count", @@ -229,6 +230,8 @@ def validate_fc_metrics(metrics): "vsock_fails", "serial_count", "serial_fails", + "hotplug_memory_count", + "hotplug_memory_fails", ], "seccomp": [ "num_faults", @@ -297,6 +300,11 @@ def validate_fc_metrics(metrics): "entropy_rate_limiter_throttled", "rate_limiter_event_count", ], + "memory_hotplug": [ + "activate_fails", + "queue_event_fails", + "queue_event_count", + ], } # validate timestamp before jsonschema validation which some more time diff --git a/tests/host_tools/memory.py b/tests/host_tools/memory.py index d9c2a01fe06..134147724cd 100644 --- a/tests/host_tools/memory.py +++ b/tests/host_tools/memory.py @@ -17,8 +17,8 @@ class MemoryUsageExceededError(Exception): def __init__(self, usage, threshold, *args): """Compose the error message containing the memory consumption.""" super().__init__( - f"Memory usage ({usage / 1 << 20:.2f} MiB) exceeded maximum threshold " - f"({threshold / 1 << 20} MiB)", + f"Memory usage ({usage / (1 << 20):.2f} MiB) exceeded maximum threshold " + f"({threshold / (1 << 20)} MiB)", *args, ) diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 32527e5c905..81454559990 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -981,6 +981,39 @@ def test_api_entropy(uvm_plain): test_microvm.api.entropy.put() +def test_api_memory_hotplug(uvm_plain): + """ + Test hotplug related API commands. + """ + test_microvm = uvm_plain + test_microvm.spawn() + test_microvm.basic_config() + + # Adding hotplug memory region should be OK. + test_microvm.api.memory_hotplug.put( + total_size_mib=1024, block_size_mib=128, slot_size_mib=1024 + ) + + # Overwriting an existing should be OK. + # Omitting optional values should be ok + test_microvm.api.memory_hotplug.put(total_size_mib=1024) + + # Get API should be rejected before boot + with pytest.raises(AssertionError): + test_microvm.api.memory_hotplug.get() + + # Start the microvm + test_microvm.start() + + # Put API should be rejected after boot + with pytest.raises(RuntimeError, match=NOT_SUPPORTED_AFTER_START): + test_microvm.api.memory_hotplug.put(total_size_mib=1024) + + # Get API should work after boot + status = test_microvm.api.memory_hotplug.get().json() + assert status["total_size_mib"] == 1024 + + def test_api_balloon(uvm_nano): """ Test balloon related API commands. @@ -1097,6 +1130,13 @@ def test_get_full_config_after_restoring_snapshot(microvm_factory, uvm_nano): uvm_nano.api.vsock.put(guest_cid=15, uds_path="vsock.sock") setup_cfg["vsock"] = {"guest_cid": 15, "uds_path": "vsock.sock"} + setup_cfg["memory-hotplug"] = { + "total_size_mib": 1024, + "block_size_mib": 128, + "slot_size_mib": 1024, + } + uvm_nano.api.memory_hotplug.put(**setup_cfg["memory-hotplug"]) + setup_cfg["logger"] = None setup_cfg["metrics"] = None setup_cfg["mmds-config"] = { @@ -1208,6 +1248,14 @@ def test_get_full_config(uvm_plain): response = test_microvm.api.vsock.put(guest_cid=15, uds_path="vsock.sock") expected_cfg["vsock"] = {"guest_cid": 15, "uds_path": "vsock.sock"} + # Add hot-pluggable memory. + expected_cfg["memory-hotplug"] = { + "total_size_mib": 1024, + "block_size_mib": 128, + "slot_size_mib": 1024, + } + test_microvm.api.memory_hotplug.put(**expected_cfg["memory-hotplug"]) + # Add a net device. iface_id = "1" tapname = test_microvm.id[:8] + "tap" + iface_id diff --git a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py index 78ea0380f1b..012e1c7d3e7 100644 --- a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py +++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py @@ -180,10 +180,6 @@ def test_host_vs_guest_cpu_features(uvm_plain_any): assert guest_feats - host_feats == AMD_GUEST_ONLY_FEATS - case CpuModel.INTEL_SKYLAKE: - assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS - assert guest_feats - host_feats == INTEL_GUEST_ONLY_FEATS - case CpuModel.INTEL_CASCADELAKE: expected_host_minus_guest = INTEL_HOST_ONLY_FEATS expected_guest_minus_host = INTEL_GUEST_ONLY_FEATS diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py index 8e25d92b7d0..bf37139a685 100644 --- a/tests/integration_tests/functional/test_cpu_features_x86_64.py +++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py @@ -1084,31 +1084,6 @@ def check_enabled_features(test_microvm, cpu_template): ) -def test_c3_on_skylake_show_warning(uvm_plain, cpu_template_any): - """ - This test verifies that the warning message about MMIO stale data mitigation - is displayed only on Intel Skylake with static C3 template. - """ - uvm = uvm_plain - uvm.spawn() - uvm.basic_config(vcpu_count=2, mem_size_mib=256) - uvm.add_net_iface() - uvm.set_cpu_template(cpu_template_any) - uvm.start() - - message = ( - "On processors that do not enumerate FBSDP_NO, PSDP_NO and " - "SBDR_SSDP_NO on IA32_ARCH_CAPABILITIES MSR, the guest kernel " - "does not apply the mitigation against MMIO stale data " - "vulnerability." - ) - - if cpu_template_any == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE": - assert message in uvm.log_data - else: - assert message not in uvm.log_data - - @pytest.mark.skipif( global_props.cpu_codename != "INTEL_SAPPHIRE_RAPIDS" or global_props.host_linux_version_tpl < (5, 17), diff --git a/tests/integration_tests/functional/test_memory_hp.py b/tests/integration_tests/functional/test_memory_hp.py new file mode 100644 index 00000000000..b2132d6c9ed --- /dev/null +++ b/tests/integration_tests/functional/test_memory_hp.py @@ -0,0 +1,38 @@ +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Tests for verifying the virtio-mem is working correctly""" + + +def test_virtio_mem_detected(uvm_plain_6_1): + """ + Check that the guest kernel has enabled PV steal time. + """ + uvm = uvm_plain_6_1 + uvm.spawn() + uvm.memory_monitor = None + uvm.basic_config( + boot_args="console=ttyS0 reboot=k panic=1 memhp_default_state=online_movable" + ) + uvm.add_net_iface() + uvm.api.memory_hotplug.put(total_size_mib=1024) + uvm.start() + + _, stdout, _ = uvm.ssh.check_output("dmesg | grep 'virtio_mem'") + for line in stdout.splitlines(): + _, key, value = line.strip().split(":") + key = key.strip() + value = int(value.strip(), base=0) + match key: + case "start address": + assert value == (512 << 30), "start address doesn't match" + case "region size": + assert value == 1024 << 20, "region size doesn't match" + case "device block size": + assert value == 2 << 20, "block size doesn't match" + case "plugged size": + assert value == 0, "plugged size doesn't match" + case "requested size": + assert value == 0, "requested size doesn't match" + case _: + continue diff --git a/tests/integration_tests/performance/test_vsock.py b/tests/integration_tests/performance/test_vsock.py index 9c705e665b7..fa4c3a5abb5 100644 --- a/tests/integration_tests/performance/test_vsock.py +++ b/tests/integration_tests/performance/test_vsock.py @@ -41,6 +41,11 @@ def __init__(self, microvm, mode, payload_length): iperf="/usr/local/bin/iperf3-vsock", payload_length=payload_length, ) + # The rootfs does not have iperf3-vsock + iperf3_guest = "/tmp/iperf3-vsock" + + self._microvm.ssh.scp_put(self._iperf, iperf3_guest) + self._guest_iperf = iperf3_guest def host_command(self, port_offset): return ( @@ -58,11 +63,6 @@ def spawn_iperf3_client(self, client_idx, client_mode_flag): make_host_port_path(VSOCK_UDS_PATH, self._base_port + client_idx), ) ) - # The rootfs does not have iperf3-vsock - iperf3_guest = "/tmp/iperf3-vsock" - - self._microvm.ssh.scp_put(self._iperf, iperf3_guest) - self._guest_iperf = iperf3_guest return super().spawn_iperf3_client(client_idx, client_mode_flag) def guest_command(self, port_offset): diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py index a8835f97c87..d71d4cad832 100644 --- a/tests/integration_tests/security/test_vulnerabilities.py +++ b/tests/integration_tests/security/test_vulnerabilities.py @@ -147,7 +147,7 @@ def get_vuln_files_exception_dict(template): # Exception for mmio_stale_data # ============================= # - # Guests on Intel Skylake or with T2S template + # Guests with T2S template # -------------------------------------------- # Whether mmio_stale_data is marked as "Vulnerable" or not is determined by the code here. # https://elixir.bootlin.com/linux/v6.1.46/source/arch/x86/kernel/cpu/bugs.c#L431 @@ -155,30 +155,17 @@ def get_vuln_files_exception_dict(template): # has been passed through to guests only since kernel v6.4. # https://github.com/torvalds/linux/commit/da3db168fb671f15e393b227f5c312c698ecb6ea # Thus, since the FLUSH_L1D bit is masked off prior to kernel v6.4, guests with - # IA32_ARCH_CAPABILITIES.FB_CLEAR (bit 17) = 0 (like guests on Intel Skylake and guests with - # T2S template) fall onto the second hand of the condition and fail the test. The value is - # "Vulnerable: Clear CPU buffers attempted, no microcode" on guests on Intel Skylake and guests - # with T2S template but "Mitigation: Clear CPU buffers; SMT Host state unknown" on kernel v6.4 - # or later. In any case, the kernel attempts to clear CPU buffers using VERW instruction and it + # IA32_ARCH_CAPABILITIES.FB_CLEAR (bit 17) = 0 (like guests with T2S template which presents + # an Intel Skylake CPU) fall into the MMIO_MITIGATION_UCODE_NEEDED branch, marking the + # system as vulnerable to MMIO Stale Data. + # The value is "Vulnerable: Clear CPU buffers attempted, no microcode" on guests on Intel + # Skylake and guests with T2S template but "Mitigation: Clear CPU buffers; SMT Host state + # unknown" on kernel v6.4 or later. + # In any case, the kernel attempts to clear CPU buffers using VERW instruction and it # is safe to ingore the "Vulnerable" message if the host has the microcode update applied # correctly. Here we expect the common string "Clear CPU buffers" to cover both cases. - # - # Guest on Intel Skylake with C3 template - # --------------------------------------- - # If the processor does not enumerate IA32_ARCH_CAPABILITIES.{FBSDP_NO,PSDP_NO,SBDR_SSDP_NO}, - # the kernel checks its lists of affected/unaffected processors and determines whether the - # mitigation is required, and if the processor is not included in the lists, the sysfs is marked - # as "Unknown". - # https://elixir.bootlin.com/linux/v6.1.50/source/arch/x86/kernel/cpu/common.c#L1387 - # The behavior for "Unknown" state was added in the following commit and older processors that - # are no longer serviced are not listed up. - # https://github.com/torvalds/linux/commit/7df548840c496b0141fb2404b889c346380c2b22 - # Since those bits are not set on Intel Skylake and C3 template makes guests pretend to be AWS - # C3 instance (quite old processor now) by overwriting CPUID.1H:EAX, it is impossible to avoid - # this "Unknown" state. - if global_props.cpu_codename == "INTEL_SKYLAKE" and template == "C3": - exception_dict["mmio_stale_data"] = "Unknown: No mitigations" - elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "T2S": + + if template == "T2S": exception_dict["mmio_stale_data"] = "Clear CPU buffers" return exception_dict diff --git a/tests/integration_tests/test_kani.py b/tests/integration_tests/test_kani.py index 9660dde75fc..2ef9a29de6a 100644 --- a/tests/integration_tests/test_kani.py +++ b/tests/integration_tests/test_kani.py @@ -34,7 +34,7 @@ def test_kani(results_dir): # --output-format terse is required by -j # -Z unstable-options is needed to enable the other `-Z` flags _, stdout, _ = utils.check_output( - "cargo kani -Z unstable-options -Z stubbing -Z function-contracts -Z restrict-vtable -j --output-format terse --harness-timeout 40m", + "cargo kani -Z unstable-options -Z stubbing -Z function-contracts -Z restrict-vtable -j --output-format terse --harness-timeout 40m --workspace", timeout=TIMEOUT, ) diff --git a/tools/bindgen.sh b/tools/bindgen.sh index e2529375285..7402c1242d9 100755 --- a/tools/bindgen.sh +++ b/tools/bindgen.sh @@ -105,6 +105,12 @@ fc-bindgen \ --allowlist-var "VIRTIO_ID.*" \ "$INCLUDE/linux/virtio_ids.h" >src/vmm/src/devices/virtio/generated/virtio_ids.rs +info "BINDGEN virtio_mem.h" +fc-bindgen \ + --allowlist-var "VIRTIO_MEM.*" \ + --allowlist-type "virtio_mem.*" \ + "$INCLUDE/linux/virtio_mem.h" >src/vmm/src/devices/virtio/generated/virtio_mem.rs + info "BINDGEN prctl.h" fc-bindgen \ --allowlist-var "PR_.*" \ diff --git a/tools/devctr/Dockerfile b/tools/devctr/Dockerfile index 1d81d5b37bb..85ee76e476b 100644 --- a/tools/devctr/Dockerfile +++ b/tools/devctr/Dockerfile @@ -4,7 +4,7 @@ FROM public.ecr.aws/lts/ubuntu:24.04 # The Rust toolchain layer will get updated most frequently, but we could keep the system # dependencies layer intact for much longer. -ARG RUST_TOOLCHAIN="1.87.0" +ARG RUST_TOOLCHAIN="1.89.0" ARG TMP_BUILD_DIR=/tmp/build ARG DEBIAN_FRONTEND=noninteractive ARG PIP_BREAK_SYSTEM_PACKAGES=1 @@ -122,7 +122,7 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-too && rustup component add llvm-tools-preview clippy rustfmt \ && cargo install --locked cargo-audit grcov cargo-sort cargo-afl \ && cargo install --locked cargo-deny --version 0.17.0 \ - && cargo install --locked kani-verifier && cargo kani setup \ + && cargo install --locked kani-verifier --version 0.64.0 && cargo kani setup \ \ && NIGHTLY_TOOLCHAIN=$(rustup toolchain list | grep nightly | tr -d '\n') \ && rustup component add rust-src --toolchain "$NIGHTLY_TOOLCHAIN" \ diff --git a/tools/devtool b/tools/devtool index 45580f2ae57..852bcad5f7d 100755 --- a/tools/devtool +++ b/tools/devtool @@ -68,7 +68,7 @@ DEVCTR_IMAGE_NO_TAG="public.ecr.aws/firecracker/fcuvm" # Development container tag -DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v83} +DEVCTR_IMAGE_TAG=${DEVCTR_IMAGE_TAG:-v84} # Development container image (name:tag) # This should be updated whenever we upgrade the development container. @@ -572,8 +572,9 @@ ensure_ci_artifacts() { # Fetch all the artifacts so they are local say "Fetching CI artifacts from S3" - FC_VERSION=$(cmd_sh "cd src/firecracker/src; cargo pkgid | cut -d# -f2 | cut -d. -f1-2") - S3_URL=s3://spec.ccfc.min/firecracker-ci/v$FC_VERSION/$(uname -m) + # FC_VERSION=$(cmd_sh "cd src/firecracker/src; cargo pkgid | cut -d# -f2 | cut -d. -f1-2") + # S3_URL=s3://spec.ccfc.min/firecracker-ci/v$FC_VERSION/$(uname -m) + S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.13-virtio-mem/$(uname -m) ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m) if [ ! -d "$ARTIFACTS" ]; then mkdir -pv $ARTIFACTS diff --git a/tools/test-popular-containers/build_rootfs.sh b/tools/test-popular-containers/build_rootfs.sh index 91131829e38..22c28b9cd88 100755 --- a/tools/test-popular-containers/build_rootfs.sh +++ b/tools/test-popular-containers/build_rootfs.sh @@ -24,6 +24,7 @@ function make_rootfs { ssh-keygen -f id_rsa -N "" fi cp id_rsa $rootfs.id_rsa + chmod a+r $rootfs.id_rsa truncate -s "$SIZE" "$IMG" mkfs.ext4 -F "$IMG" -d $LABEL diff --git a/tools/update-credits.sh b/tools/update-credits.sh index c6ff953b64c..6a60af30ad7 100755 --- a/tools/update-credits.sh +++ b/tools/update-credits.sh @@ -11,7 +11,6 @@ cd "$(dirname "$BASH_SOURCE")/.." { cat <<-'EOH' - # Firecracker Credits and Thanks (This file is autogenerated using [update-credits.sh](tools/update-credits.sh).)